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.
Что происходит? - и как мне решить эту проблему?