4

Django/channels newbie: I'm trying to write unit tests for my application, but I'm getting some weird behaviour from tests. I suspect it has something to do with either asynchronous code or django testing database but I'm lost.

My consumer has this kind of structure:

class GameConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['gameID']
        self.room_group_name = 'game_%s' % self.room_name

        # check something from database to decide if this connection should be rejected
        if not await self.does_game_exists():
            await self.close(4001)
        else:
            await self.accept()
            await self.channel_layer.group_add(
                self.room_group_name,
                self.channel_name
            )
            
            # insert data into db
            await self.add_player_to_game()
            

    @database_sync_to_async
    def does_game_exists(self):
        ....

    @database_sync_to_async
    def add_player_to_game(self):
        ....

This works when using the application normally; the data is inserted in the db.

Now the unit test:

class WSConsumerTest(TransactionTestCase):
    fixtures = ['test-data.yaml']

    @database_sync_to_async
    def get_num_players(self):
        ...

    @database_sync_to_async
    def create_test_game(self):
        ...

    async def test_player_is_added_on_successful_connection(self):
        game = await self.create_test_game()

        application = URLRouter([
            url(r'ws/game/(?P<gameID>[a-zA-Z0-9]{6})', consumers.GameConsumer),
        ])

        communicator = WebsocketCommunicator(application, f"/ws/game/{game.gameID}")
        connected, _ = await communicator.connect()

        player_count = await self.get_num_players()
        self.assertEqual(player_count, 1, "Player is not added in database after successful connection")

        communicator.disconnect()

This fails. get_num_players returns the number of player in the game instance created by create_test_game. I'm sure this two functions are correct, they are standard django ORM queries.

I tried running test with --keepdb option and the db is empty, not even the test game entry is created.

What am I doing wrong? Thanks in advice.

Edit

By modifying the test

async def test_player_is_added_on_successful_connection(self):
        game = await self.create_test_game()

        application = URLRouter([
            url(r'ws/game/(?P<gameID>[a-zA-Z0-9]{6})', consumers.GameConsumer),
        ])

        communicator = WebsocketCommunicator(application, f"/ws/game/{game.gameID}")
        connected, _ = await communicator.connect()

        self.assertTrue(connected)

        player_count = await self.get_num_players()
        self.assertEqual(player_count, 1, "Player is not added in database after successful connection")

        communicator.disconnect()

the test fails because the connection is rejected. It's rejected because the consumer doesn't find the game entry in the db; but if I search for the game in the database in the test method, the game is found.

Do tests and consumers use different databases?

tino
  • 151
  • 3
  • 9
  • It seems https://stackoverflow.com/questions/56175352/ is related, I suggest anyone facing the same issue to test related solution – Jean Bouvattier Dec 13 '21 at 15:03

0 Answers0