Gab*_*Muj 4 django factory-boy
我正在使用 factory_boy 包并DjangoModelFactory生成带有静音信号的工厂模型
@factory.django.mute_signals(signals.post_save)
class SomeModelTargetFactory(DjangoModelFactory):
name = factory.Sequence(lambda x: "Name #{}".format(x))
...
Run Code Online (Sandbox Code Playgroud)
我有一个post_save连接到模型的信号:
def send_notification(sender, instance, created, **kwargs):
if created:
send_email(...)
post_save.connect(send_notification, SomeModel)
Run Code Online (Sandbox Code Playgroud)
当我使用工厂类创建模型的实例时,如何测试信号是否有效?
Ken*_*ton 10
直接问题的一些解决方案。其次是谨慎。
@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)
Run Code Online (Sandbox Code Playgroud)
注意:在 3.3 中加入标准库之前,mock 是单独的包
默认情况下,这将使信号保持打开状态,但您可以有选择地禁用:
def test_without_signals(self):
with factory.django.mute_signals(signals.post_save):
my_obj = SomeModelTargetFactory()
# ... perform actions w/o signals and assert ...
Run Code Online (Sandbox Code Playgroud)
class SomeModelTargetFactory(DjangoModelFactory):
name = factory.Sequence(lambda x: "Name #{}".format(x))
# ...
@factory.django.mute_signals(signals.post_save)
class SomeModelTargetFactoryNoSignals(SomeModelTargetFactory):
pass
Run Code Online (Sandbox Code Playgroud)
我从来没有试过这个,但它似乎应该工作。此外,如果您只需要对象用于不需要持久性的快速单元测试,那么FactoryBoy 的 BUILD 策略可能是一个可行的选择。
关于如何在您自己的代码中使用信号会造成错误的解耦感,有很容易找到的参考资料(post_save例如,本质上与覆盖和扩展save方法相同。我会让您研究一下,看看它是否适用于您的使用案件。
肯定会三思而后行将其设为默认值。
更安全的方法是“静音”/模拟接收者/副作用,而不是发送者。
第三方包经常使用默认的 Django 模型信号。由于包内交互,静音这些可以隐藏难以追踪的错误。
定义和调用(然后在需要时静音)你自己的信号更好,但通常只是重新发明一个方法调用。Sentry 是在大型代码库中很好地使用信号的一个很好的例子。
解决方案 A 是迄今为止最明确和最安全的。解决方案 B 和 C,不添加您自己的信号需要小心和注意。
我不会说post_save完全静音没有用例。它应该是一个例外和警报,可能首先要仔细检查需求。
| 归档时间: |
|
| 查看次数: |
2152 次 |
| 最近记录: |