Search code examples
djangopython-asynciodjango-channels

Why is it not possible to use the AsyncClient to login without using sync_to_async?


According to the documentation about testing async functions in Django 3.1, it should be possible to simply await the async client methods in an async context without having to wrap it in sync_to_async or database_sync_to_async as it implements all methods. Is there a way around this?

The first request works, but the second and third do not.

class TestAsyncClient(TransactionTestCase):
    def setUp(self):
        self.async_client = AsyncClient()
        self.user = get_user_model().objects.create_user("user_a@example.com", "passwd_a")

    async def test_async_login(self):
        """Use the async client to login without using sync_to_async"""

        request = await self.async_client.get("/")
        self.assertTrue(request)
        
        logged_in = await self.async_client.login(
            username="user_a@example.com", password="passwd_a"
        )
        self.assertTrue(logged_in)

        logged_in = await self.async_client.force_login(self.user)
        self.assertTrue(logged_in)

Solution

  • First of all, you get a response, not a request.

    What evaluates to True, would be response.ok.

    However, async_client.login is not an async method and does not send a request, same with force_login. They simply fake a session with a logged in user and are synchronous (with database access if your SESSION_STORE is ModelBackend).