将factory_boy与静音信号一起使用时如何测试信号 [英] How to test signals when using factory_boy with muted signals
问题描述
我正在使用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屋!