Ste*_*noP 43 python django signals mocking django-signals
我有一个通过装饰器连接的signal_handler,这个非常简单:
@receiver(post_save, sender=User,
dispatch_uid='myfile.signal_handler_post_save_user')
def signal_handler_post_save_user(sender, *args, **kwargs):
# do stuff
Run Code Online (Sandbox Code Playgroud)
我想做的是在测试中使用模拟库http://www.voidspace.org.uk/python/mock/进行模拟,以检查django调用它的次数.我的代码目前是这样的:
def test_cache():
with mock.patch('myapp.myfile.signal_handler_post_save_user') as mocked_handler:
# do stuff that will call the post_save of User
self.assert_equal(mocked_handler.call_count, 1)
Run Code Online (Sandbox Code Playgroud)
这里的问题是即使被模拟也会调用原始的信号处理程序,这很可能是因为@receiver装饰器正在某处存储信号处理程序的副本,所以我在嘲笑错误的代码.
所以问题是:如何模拟我的信号处理程序以使我的测试工作?
请注意,如果我将信号处理程序更改为:
def _support_function(*args, **kwargs):
# do stuff
@receiver(post_save, sender=User,
dispatch_uid='myfile.signal_handler_post_save_user')
def signal_handler_post_save_user(sender, *args, **kwargs):
_support_function(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
而我嘲笑_support_function,一切都按预期工作.
Mei*_*tro 19
可能更好的想法是模拟信号处理程序内部的功能而不是处理程序本身.使用OP的代码:
@receiver(post_save, sender=User, dispatch_uid='myfile.signal_handler_post_save_user')
def signal_handler_post_save_user(sender, *args, **kwargs):
do_stuff() # <-- mock this
def do_stuff():
... do stuff in here
Run Code Online (Sandbox Code Playgroud)
然后模拟do_stuff:
with mock.patch('myapp.myfile.do_stuff') as mocked_handler:
self.assert_equal(mocked_handler.call_count, 1)
Run Code Online (Sandbox Code Playgroud)
Ste*_*noP 18
所以,我最终得到了一种解决方案:模拟信号处理程序只是意味着将模拟本身连接到信号,所以这正是我所做的:
def test_cache():
with mock.patch('myapp.myfile.signal_handler_post_save_user', autospec=True) as mocked_handler:
post_save.connect(mocked_handler, sender=User, dispatch_uid='test_cache_mocked_handler')
# do stuff that will call the post_save of User
self.assertEquals(mocked_handler.call_count, 1) # standard django
# self.assert_equal(mocked_handler.call_count, 1) # when using django-nose
Run Code Online (Sandbox Code Playgroud)
请注意,autospec=True在mock.patch是为了使需要post_save.connect对一个正常工作MagicMock,否则Django将提高一些例外,连接将失败.