将factory_boy与静音信号一起使用时如何测试信号 [英] How to test signals when using factory_boy with muted signals

查看:96
本文介绍了将factory_boy与静音信号一起使用时如何测试信号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用factory_boy包和 DjangoModelFactory 生成具有静音信号的工厂模型

I am using factory_boy package and DjangoModelFactory to generate a factory model with muted signals

<代码>@ factory.django.mute_signals(signals.post_save)类SomeModelTargetFactory(DjangoModelFactory):名称= factory.Sequence(lambda x:名称#{}".format(x))...

我有一个 post_save 信号连接到模型:def send_notification(发送方,实例,创建的,** kwargs):如果创建:发送电子邮件(...)post_save.connect(send_notification,SomeModel)

I have a post_save signal connected to the model: def send_notification(sender, instance, created, **kwargs): if created: send_email(...) post_save.connect(send_notification, SomeModel)

使用factory类创建模型实例时,如何测试信号的正常工作?

How can I test the signals works when I create an instance of the model using the factory class?

推荐答案

一些针对直接问题的解决方案.紧随其后.

Some solutions for the direct question. Followed by a caution.

@mock.patch('send_email')
def test_mocking_signal_side_effects(self, mocked_send_email):
    my_obj = SomeModelTargetFactory()

    # mocked version of send_email was called
    self.assertEqual(mocked_send_email.call_count, 1)

    my_obj.foo = 'bar'
    my_obj.save()

    # didn't call send_email again
    self.assertEqual(mocked_send_email.call_count, 1)

注意:模拟程序是在3.3中加入标准lib之前的独立程序包.

默认情况下,这将使信号保持打开状态,但是您可以有选择地禁用:

This would leave the signals on by default, but you can selectively disable:

def test_without_signals(self):
    with factory.django.mute_signals(signals.post_save):
        my_obj = SomeModelTargetFactory()

        # ... perform actions w/o signals and assert  ...

C)静音信号和基础工厂的扩展版本

class SomeModelTargetFactory(DjangoModelFactory):
    name = factory.Sequence(lambda x: "Name #{}".format(x))
    # ...


@factory.django.mute_signals(signals.post_save)
class SomeModelTargetFactoryNoSignals(SomeModelTargetFactory):
    pass

我从没有尝试过,但似乎应该可以.此外,如果您只需要对象以进行不需要持久性的快速单元测试,则可能

I've never tried this, but it seems like it should work. Additionally, if you just need the objects for a quick unit test where persistence isn't required, maybe FactoryBoy's BUILD strategy is a viable option.

关于在您自己的代码中使用信号如何造成虚假的去耦感的参考文献很容易找到(例如, post_save 本质上与重写和扩展相同 save 方法.我将让您研究一下它是否适用于您的用例.

There are easily findable references about how using signals in your own code can create a false sense of decoupling (post_save for example, essentially is the same as overriding and extending the save method. I'll let you research that to see if it applies to your use case.

对于将其设置为默认值,肯定会三思而后行.

Would definitely think twice about making it the default.

一种更安全的方法是静音"/模拟接收方/副作用,而不是发送方.

默认Django模型信号经常被第三方软件包使用.由于程序包内部的交互作用,将这些变量静音可能难以隐藏错误.

The default Django model signals are used frequently by third party packages. Muting those can hide hard to track down bugs due to intra-package interaction.

定义和调用(然后根据需要将其静音)自己的信号更好,但通常只是重新发明了一个方法调用.哨兵是在大型代码库中良好使用信号的一个很好的例子.

Defining and calling (and then muting if needed) your own signals is better, but often is just re-inventing a method call. Sentry is a good example of signals being used well in a large codebase.

解决方案A是迄今为止最明确,最安全的解决方案.解决方案B和C,无需添加您自己的信号,需要引起注意.

Solution A is by far the most explicit and safe. Solution B and C, without the addition of your own signal requires care and attention.

我不会说完全没有静音 post_save 的用例.应该是一个例外,并且应该提醒您首先要仔细检查需求.

I wont say there are no use cases for muting post_save entirely. It should be an exception and an alert to maybe double check the need in the first place.

这篇关于将factory_boy与静音信号一起使用时如何测试信号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆