django - How to test signals when using factory_boy with muted signals -


i using factory_boy package , djangomodelfactory generate factory model muted signals

@factory.django.mute_signals(signals.post_save) class somemodeltargetfactory(djangomodelfactory): name = factory.sequence(lambda x: "name #{}".format(x)) ...

i have post_save signal connected model: def send_notification(sender, instance, created, **kwargs): if created: send_email(...) post_save.connect(send_notification, somemodel)

how can test signals works when create instance of model using factory class?

some solutions direct question. followed caution.

a) instead of turning off signals, mock side effects

@mock.patch('send_email') def test_mocking_signal_side_effects(self, mocked_send_email):     my_obj = somemodeltargetfactory()      # mocked version of send_email 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) 

note: mock separate package before joining standard lib in 3.3

b) use context manager can selectively disable in tests

this leave signals on default, can selectively disable:

def test_without_signals(self):     factory.django.mute_signals(signals.post_save):         my_obj = somemodeltargetfactory()          # ... perform actions w/o signals , assert  ... 

c) mute signals , extended version of base factory

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, seems should work. additionally, if need objects quick unit test persistence isn't required, maybe factoryboy's build strategy viable option.

caution: muting signals, post_save can hide nasty bugs

there findable references how using signals in own code can create false sense of decoupling (post_save example, essentially same overriding , extending save method. i'll let research see if applies use case.

would think twice making default.

a safer approach "mute"/mock receiver/side effect, not sender.

the default django model signals used third party packages. muting can hide hard track down bugs due intra-package interaction.

defining , calling (and muting if needed) your own signals better, re-inventing method call. sentry example of signals being used in large codebase.

solution far explicit , safe. solution b , c, without addition of own signal requires care , attention.

i wont there no use cases muting post_save entirely. should exception , alert maybe double check need in first place.


Comments

Popular posts from this blog

html - How to custom Bootstrap grid height? -

javascript - pass values from mssql to views in node -

javascript - Understanding ExtJS Framework Syntax -