测试我已连接到Django中的特定信号

Ctr*_*spc 6 python testing django

我有一个名为"publisher"的Django应用程序,它连接到我的django项目中的各种信号,当它收到它们时,它会向rabbitmq队列发送一条消息.我想要做的是能够测试我的设置代码是否连接到正确的信号.

我的app结构如下:

publisher
    - __init__.py
    - signals.py
    - tests.py
Run Code Online (Sandbox Code Playgroud)

我的__init__.py看起来像:

import signals
Run Code Online (Sandbox Code Playgroud)

和我的signals.py:

def receiver_function(*args, **kwargs):
    #Does rabbitmq stuff

my_interesting_signal.connect(receiver_function)
Run Code Online (Sandbox Code Playgroud)

我已经考虑过修补接收器功能,并在发送信号时检查模拟是否被调用:

tests.py:

class SignalsTeste(TestCase):

    def_test_connection(self):

        with patch('publisher.signals.receiver_function') as receiver_mock:
            my_interesting_signal.application_created.send(None)
            self.assertEquals(receiver_mock.call_count, 1)
Run Code Online (Sandbox Code Playgroud)

但是,由于信号模块是导入的,因此信号连接是在测试运行之前进行的,因此在修补函数之前进行连接时,这种方法不起作用......

任何人都可以建议另类策略吗?

Fra*_*k T 12

我遇到了你描述的同样的嘲弄问题.我的解决方案是进入Django的信号注册表并声明我的函数已使用正确的信号注册.

这是我的测试:

def test_signal_registry(self):
    from foo.models import bar_func  # The function I want to register.
    from django.db.models import signals
    registered_functions = [r[1]() for r in signals.pre_delete.receivers]
    self.assertIn(bar_func, registered_functions)
Run Code Online (Sandbox Code Playgroud)

关于该列表理解的一点解释:

"pre_delete"是我在这种情况下关心的django.dispatch.dispatcher.Signal的实例.您将在示例中使用自己的"my_interesting_signal".信号有一个称为"接收器"的内部属性,它是一个两元组的列表,其中第二个元素是你注册的函数的弱参数(因此r [1]).调用weakref会返回指示对象.

我不得不玩弱点来解决这个问题:

import weakref
def foo():
    pass
w = weakref.ref(foo)
w() == foo
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

  • 我认为这不太正确。如果 bar_func 在 `models.py` 中,那么,是的,它将被 Django 自动导入并因此连接到信号。但如果它在“signals.py”中,则不一定。此外,在测试中导入接收器的行为会自动连接它,因此即使您没有在其他地方连接它,测试也会通过。 (2认同)

小智 5

测试信号是否已连接的一种方法是断开信号并检查此操作的结果。如果信号断开或没有断开,则调用<some_signal>.disconnect(...)返回。TrueFalse

例如,我们想测试post_save信号是否连接到我们的receiver_function.

模块.py

def receiver_function(*args, **kwargs):
    pass

signals.post_save.connect(receiver_function)
Run Code Online (Sandbox Code Playgroud)

测试.py

class SignalsTest(TestCase):
    def test_connection(self):
        result = signals.post_save.disconnect(receiver_function)

        self.assertTrue(result)
Run Code Online (Sandbox Code Playgroud)

调用必须使用与call( , )disconnect相同的参数connectsenderdispatch_uid

测试完毕后需要重新连接信号,否则会保持断开状态