Max Malysh
Max Malysh

Reputation: 31615

Django 3.0 — database connections are not closed after async tests

I use Django ORM inside async code. Everything works fine and all tests pass. However, DB connections do not close properly after tests. Here is an example:

from asgiref.sync import sync_to_async, async_to_sync


@sync_to_async
def count_books():
    return Book.objects.count()


class FooTest(TestCase):
    def setUp(self):
        Book.objects.create(title='Haha')

    def test1(self):
        import asyncio
        c = asyncio.run(count_books())
        self.assertEqual(1, c)

    def test2(self):
        c = async_to_sync(count_books)()
        self.assertEqual(1, c)

Postgres error:

django.db.utils.OperationalError: database "test_mydbname" is being accessed by other users

Sqlite error:

sqlite3.OperationalError: database table is locked: test_mydbname

I've tried swapping sync_to_async with database_sync_to_async from django-channels, but this didn't change anything.

How can I fix this?

Upvotes: 6

Views: 2150

Answers (1)

Matthaus Woolard
Matthaus Woolard

Reputation: 2408

The issue comes with how your async runloops are interacting with the main thread, handling this yourself can get quite complex.

For testing django-channels I suggest using pytest with pytest-asyncio for testing channels. And of course pytest-django.

This will provide a few useful tools for testing async code.

@pytest.mark.django_db(transaction=True)
@pytest.mark.asyncio
async def test1():
    count = await database_sync_to_async(Book.objects.count)
    ....

for some examples of how to test channels code take a look here.

Upvotes: 2

Related Questions