0

So, I didn't use channels for a very long time, so let's be that this is a first time that I have tried to do something.

I am trying to create 1 Consumer, wrapped with 1 custom Auth middleware and I want to test my Consumer, if it behaves properly in various test cases.

Django==4.1.7
channels==4.0.0

middleware.py

@database_sync_to_async
def get_user(email):
    user = User.objects.get(email=email)
    if not user.is_active:
        raise AuthenticationFailed("User is inactive", code="user_inactive")
    return user


class OktaASGIMiddleware(BaseMiddleware):
    def __init__(self, inner):
        super().__init__(inner)
        self.okta_auth = OKTAAuthentication()

    async def __call__(self, scope, receive, send):
        try:
            # token checking and retrieval 
            claims = self.okta_auth.jwt_verifier.parse_token(token)[1]
            user = await get_user(claims["email"])
            scope["user"] = user
        except Exception as exc:
            await send({"type": "websocket.close"})
            raise
        return await self.inner(scope, receive, send)

tests.py

    @aioresponses()
    async def test_connect_with_correct_token_edit_resource_draft(
        self, mocked_io_request
    ):
        mocked_io_request.get(
            # mocked request/respones
        )

        communicator = WebsocketCommunicator(
            application, f"/ws/draft/1/?token={sometoken}"
        )
        connected, subprotocol = await communicator.connect()
        self.assertTrue(connected)

So, the issue is, when I use database_sync_to_async as Docs suggests, I am getting:

django.db.utils.InterfaceError: connection already closed.

When I use from asgiref.sync import sync_to_async, everything works fine and I can test my consumer properly.

Also, i an attempt to avoid database_sync_to_async, I switched from JsonWebsocketConsumer to AsyncJsonWebsocketConsumer, but still no help.

NOTE: Both of this code works well when the app is running and you connect to Websocket through Browser extension or using Javascript.

What's missing here, and why I can't make tests work with database_sync_to_async and with JsonWebsocketConsumer?

I do not want to have a lot of created connections, and I want to use database_sync_to_async as Docs suggest.

I hope you can help me.

milutinke
  • 401
  • 1
  • 4
  • 13

1 Answers1

0

Okay.

So the issue was that in my TestCase I inherited TestCase from django.test.

Testing django channels and consumers with TestCase, won't work. For async support, it should be used TransactionTestCase, which provides better support for asynchronous code.

TransactionTestCase wraps each test method in a database transaction, and since it also supports asynchronous code, it can be used for testing Django Channels without the issues associated with TestCase.

milutinke
  • 401
  • 1
  • 4
  • 13
  • This solved the problem on MacOS, but I still have issue on Linux. Tests are still getting stuck on ubuntu image, can anyone help? :) – milutinke Apr 19 '23 at 12:37