Search code examples
python-3.xasynchronoustestingpatch

Why is my async python test of assert_awaited_once_with not working?


I am using django and calling the queryset method async_create method like so:

class TemperatureQueue(typing.List[models.Temperature]):
    __que_commit_size = 10

    async def add(self, item: models.Temperature):
        self.append(item)
        if len(self) >= self.__que_commit_size:
            items = list(self)
            await models.Temperature.objects.abulk_create(items)
            self.clear()

In my test code I am trying to assert that the async method is called:

import datetime

from unittest.mock import patch, AsyncMock, MagicMock
from django.db.models import QuerySet

from django.test import TestCase

class TestTemperatureQueue(TestCase):
    @patch.object(QuerySet, 'abulk_create')
    async def test_add_ten(self, mock_bulk_create: AsyncMock):
        from temperature import models
        from temperature.management.commands import ingest_temps
        items = [models.Temperature(value=i, timestamp=datetime.datetime.now(tz=datetime.timezone.utc)) for i in range(10)]
        queue = ingest_temps.TemperatureQueue([])
        for i, item in enumerate(items):
            await queue.add(item)
            if i < 9:
                assert len(queue) == i + 1
                assert queue == items[:i+1]
                continue
            assert len(queue) == 0
        assert mock_bulk_create.assert_awaited_once_with(items)

But this test line does not work and reports:

E       AssertionError: assert None
E        +  where None = <bound method AsyncMockMixin.assert_awaited_once_with of <AsyncMock name='abulk_create' id='4463938672'>>([<Temperature: Temperature(id=None, value=0, timestamp=2024-02-06 18:19:31.981964+00:00)>, <Temperature: Temperature(i...18:19:31.982066+00:00)>, <Temperature: Temperature(id=None, value=5, timestamp=2024-02-06 18:19:31.982078+00:00)>, ...])
E        +    where <bound method AsyncMockMixin.assert_awaited_once_with of <AsyncMock name='abulk_create' id='4463938672'>> = <AsyncMock name='abulk_create' id='4463938672'>.assert_awaited_once_with

It does see that it is called one and awaited once. Checking assert_called_once_with and assert_awaited_once_with is not working. Why not? How do I get this to work?


Solution

  • The assert_* methods raise an exception if the condition was not met, otherwise they return None.

    So you should remove the assert:

    mock_bulk_create.assert_awaited_once_with(items)