正确测试Django信号的方法
我正在尝试测试发送的信号以及它的提供参数。这个信号是在 contact_question_create
视图中,在表单提交后触发的。
我的测试案例大致是这样的:
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')
这样测试这个信号合适吗?有没有更好的方法?
7 个回答
23
我有一个替代的建议,使用的是mock
库,这个库现在已经成为Python 3标准库中的unittest.mock
的一部分(如果你在用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")
这个建议的关键部分是模拟一个接收器,然后测试你的信号是否被发送到这个接收器,并且只被调用一次。这非常好,特别是当你有自定义信号,或者你写了发送信号的方法时,你想在单元测试中确保这些信号确实被发送了。
40
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.
通过这个,你就可以测试你的信号是否正确触发了。
10
我自己解决了这个问题。我觉得最好的办法是这样的:
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')