Правильный способ тестирования сигналов Django
Я пытаюсь проверить переданный сигнал и его обеспечение_арги. Сигнал запускается внутри contact_question_create
только после отправки формы.
My TestCase - это что-то вроде:
def test_form_should_post_proper_data_via_signal(self):
form_data = {'name': 'Jan Nowak'}
signals.question_posted.send(sender='test', form_data=form_data)
@receiver(signals.question_posted, sender='test')
def question_posted_listener(sender, form_data):
self.name = form_data['name']
eq_(self.name, 'Jan Nowak')
Это правильный способ проверить этот сигнал? Любые лучшие идеи?
Ответы
Ответ 1
Я решил проблему самостоятельно. Я думаю, что лучшее решение следующее:
def test_form_should_post_proper_data_via_signal(self):
# define the local listener
def question_posted_listener(sender, form_data, **kwargs):
self.name = form_data['name']
# prepare fake data
form_data = {'name': 'Jan Nowak'}
# connect & send the signal
signals.question_posted.connect(question_posted_listener, sender='test')
signals.question_posted.send(sender='test', form_data=form_data)
# check results
eq_(self.name, 'Jan Nowak')
Ответ 2
Самый простой способ сделать то, что вы просили в 2015 году:
from unittest.mock import patch
@patch('full.path.to.signals.question_posted.send')
def test_question_posted_signal_triggered(self, mock):
form = YourForm()
form.cleaned_data = {'name': 'Jan Nowak'}
form.save()
# Check that your signal was called.
self.assertTrue(mock.called)
# Check that your signal was called only once.
self.assertEqual(mock.call_count, 1)
# Do whatever else, like actually checking if your signal logic did well.
И с этим вы только что протестировали, что ваш сигнал был правильно запущен.
Ответ 3
У меня есть альтернативное предложение, использующее библиотеку mock
, которая теперь является частью стандартной библиотеки unittest.mock
в Python 3 (если вы используете Python 2, вам придется pip install mock
).
try:
from unittest.mock import MagicMock
except ImportError:
from mock import MagicMock
def test_form_should_post_proper_data_via_signal(self):
"""
Assert signal is sent with proper arguments
"""
# Create handler
handler = MagicMock()
signals.question_posted.connect(handler, sender='test')
# Post the form or do what it takes to send the signal
signals.question_posted.send(sender='test', form_data=form_data)
# Assert the signal was called only once with the args
handler.assert_called_once_with(signal=signals.question_posted, form_data=form_data, sender="test")
Основная часть предложения заключается в том, чтобы смоделировать приемник, а затем проверить, передается ли ваш сигнал этому приемнику и вызывается только один раз. Это замечательно, особенно если у вас есть пользовательские сигналы или вы написали методы, которые отправляют сигналы, и вы хотите убедиться, что они отправляются в ваших модульных тестах.
Ответ 4
Вам необходимо:
- утверждать, что сигнал был испущен с соответствующими аргументами и,
- определенное количество раз и,
- в соответствующем порядке.
Вы можете использовать mock_django приложение, которое обеспечивает mock для сигналов.
Пример:
from mock import call
def test_install_dependency(self):
with mock_signal_receiver(post_app_install) as install_receiver:
self.env.install(self.music_app)
self.assertEqual(install_receiver.call_args_list, [
call(signal=post_app_install, sender=self.env,
app=self.ukulele_app),
call(signal=post_app_install, sender=self.env,
app=self.music_app),
])
Ответ 5
Целью этого является не проверка базового механизма сигнализации, а важная unit test, чтобы гарантировать, что любой сигнал, который должен испускать ваш метод, фактически испускается соответствующими аргументами. В этом случае это кажется немного тривиальным, поскольку он является внутренним сигналом джанго, но представьте, если бы вы написали метод, который излучал пользовательский сигнал.
Ответ 6
Почему вы тестируете свою инфраструктуру? Django уже имеет модульные тесты для диспетчера сигналов. Если вы не верите, что ваша инфраструктура в порядке, просто прикрепите ее модульные тесты к вашему тестовому бегуну.