Django unittests + mock в тестировании сигналов : AssertionError: ожидаемый вызов не найден (хотя фактические и ожидаемые значения совпадают)

Я использую Django 3.2

Я пишу unittests для тестирования некоторых пользовательских сигналов. Вот (обязательно упрощенная) версия кода, который я тестирую:

/path/to/project/myapp/models.py

from .signals import signal_comment
from .constants import EVENT_COMMENT_DELETE

class Commentable(models.Model):

    def delete_comment(actor, *args, **kwargs):
        # do some checking etc ...
        signal_comment.send(sender= self.__class__, instance=self, comment_instance=comment, event_type = EVENT_COMMENT_DELETE, actor=actor) 

    class Meta:
        abstract = True



class InterestingArtefact(Commentable):
    pass   
<
from django.dispatch import Signal
# ...
signal_comment = Signal()
<
from unittest.mock import MagicMock


class CatchSignal:

    def __init__(self, signal):
        self.signal = signal
        self.handler = MagicMock()


    def __enter__(self):
        self.signal.connect(self.handler)
        return self


    def __exit__(self, exc_type, exc_value, tb):
        self.signal.disconnect(self.handler)


class TestCommentModels(TestCase):
# ...
    
    def test_delete_comment_signal_emits_correct_data(self):

        with CatchSignal(signal_comment) as catcher:

            the_signal = catcher.signal
            handler = catcher.handler

            # Create comment (not using InterestingArtefact.add_comment(), so signal not sent on creation)
            ct = ContentType.objects.get_for_model(self.artefact)
            oid = self.artefact.id

            comment = Comment.objects.create(content_type=ct, object_id=oid, body='Hello world!', actor=self.approved_user)

            # is_ok, comment = self.artefact.add_comment(self.approved_user, **self.cparms_plain_text)
            self.assertIsInstance(comment, Comment)
            self.artefact.delete_comment(self.approved_user, comment.id)

            handler.assert_called_once_with(
                signal = the_signal,
                sender = InterestingArtefact,
                instance = self.artefact,
                comment_instance = comment,
                event_type = EVENT_COMMENT_DELETE,
                actor = self.approved_user
            )
<
in test_delete_comment_signal_emits_correct_data
    handler.assert_called_once_with(
  File "/usr/lib/python3.8/unittest/mock.py", line 925, in assert_called_once_with
    return self.assert_called_with(*args, **kwargs)
  File "/usr/lib/python3.8/unittest/mock.py", line 913, in assert_called_with
    raise AssertionError(_error_message()) from cause
AssertionError: expected call not found.
Expected: mock(signal=<django.dispatch.dispatcher.Signal object at 0x7f76858b41c0>, sender=<class 'myapp.models.InterestingArtefact'>, instance=<InterestingArtefact: InterestingArtefact - test artefact>, comment_instance=<Comment: Hello world!>, event_type=729, actor=<User: joebloggs>)
Actual: mock(signal=<django.dispatch.dispatcher.Signal object at 0x7f76858b41c0>, sender=<class 'myapp.models.InterestingArtefact'>, instance=<InterestingArtefact: InterestingArtefact - test artefact>, comment_instance=<Comment: Hello world!>, event_type=729, actor=<User: joebloggs>)

Как видно из сообщения об ошибке выше, фактическое значение совпадает с ожидаемым, и поскольку имитационный код получает значение (т.е. фактическое), я не понимаю сообщения об ошибке: expected call not found.

Что происходит? - и как мне решить эту проблему?

Вернуться на верх