正确的方法来测试Django信号

时间:2010-09-28 21:34:29

标签: python django unit-testing tdd

我正在尝试测试已发送的信号,它正在提供._asgs。表单提交后,在contact_question_create视图内触发信号。

我的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')

这是测试此信号的正确方法吗?有更好的想法吗?

6 个答案:

答案 0 :(得分:24)

最简单的方式来做你在2015年提出的问题:

?,?

有了这个,你刚刚测试了你的信号被正确触发了。

答案 1 :(得分:11)

我有一个替代建议使用mock库,它现在是Python 3中unittest.mock标准库的一部分(如果你使用的是Python 2,你必须{{1} }})。

pip install mock

该建议的基本部分是模拟接收器,然后测试您的信号是否被发送到该接收器,并且只调用一次。这很好,特别是如果你有自定义信号,或者你已经编写了发送信号的方法,并且你想在单元测试中确保它们被发送。

答案 2 :(得分:5)

你需要:

  • 声明信号是通过适当的参数
  • 发出的
  • 特定次数
  • 以适当的顺序。

您可以使用提供mock_djangomock for signals应用。

示例:

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),
        ])

答案 3 :(得分:4)

这样做的目的不是测试底层信令机制,而是一个重要的单元测试,以确保您的方法应该发出的任何信号实际上是用适当的参数发出的。在这种情况下,它似乎有点微不足道,因为它是一个内部django信号,但想象一下,如果你编写了发出自定义信号的方法。

答案 4 :(得分:3)

我自己解决了这个问题。我认为最好的解决方案如下:

    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')

答案 5 :(得分:0)

为什么要测试你的框架? Django已经为信号调度员进行了单元测试。如果你不相信你的框架是好的,只需将它的单元测试附加到你的测试运行器上。