Django 3.0 — database connections are not closed after async tests
Asked Answered
P

1

6

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?

Protege answered 15/2, 2020 at 19:33 Comment(1)
are you try django 3.0 use motor ?Commentary
C
2

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.

Chromaticity answered 15/2, 2020 at 19:50 Comment(3)
Thanks! What if I don't use django channels at all?Protege
I have found i you need to test async python pytest-asyncio should be your go to, Pytest is very flexible and can call your regular python UnitTest classes as well so you can keep your existing test code in place for the non async code and pytest will call it very happily .Chromaticity
with respect to django3 (orm access) django does not yet provide the equivalent of database_sync_to_asyncChromaticity

© 2022 - 2024 — McMap. All rights reserved.