首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何模拟django信号处理程序?

如何模拟django信号处理程序?
EN

Stack Overflow用户
提问于 2012-10-28 19:39:27
回答 7查看 14.5K关注 0票数 53

我有一个通过装饰器连接的signal_handler,类似于这个非常简单的:

代码语言:javascript
复制
@receiver(post_save, sender=User, 
          dispatch_uid='myfile.signal_handler_post_save_user')
def signal_handler_post_save_user(sender, *args, **kwargs):
   # do stuff

我想要做的是在测试中使用模拟库 http://www.voidspace.org.uk/python/mock/来模拟它,检查django调用它多少次。我目前的代码如下:

代码语言:javascript
复制
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)

这里的问题是,即使被模拟,也会调用原始信号处理程序,这很可能是因为@receiver装饰器将信号处理程序的副本存储在某个地方,所以我在模仿错误的代码。

因此,问题是:我如何嘲笑我的信号处理程序来使我的测试工作?

请注意,如果我将信号处理程序更改为:

代码语言:javascript
复制
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)

相反,我嘲笑_support_function,一切都像预期的那样工作。

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2012-10-29 09:47:37

因此,我最终得到了一种解决方案:模拟信号处理程序仅仅意味着将模拟本身连接到信号,所以这正是我所做的:

代码语言:javascript
复制
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

注意,要使autospec=Truemock.patch上正确工作,mock.patch中的post_save.connect是必需的,否则django将引发一些异常,连接将失败。

票数 18
EN

Stack Overflow用户

发布于 2015-10-02 18:07:43

更好的方法可能是模拟信号处理程序内部的功能,而不是模拟处理程序本身。使用OP的代码:

代码语言:javascript
复制
@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

然后模拟do_stuff

代码语言:javascript
复制
with mock.patch('myapp.myfile.do_stuff') as mocked_handler:
    self.assert_equal(mocked_handler.call_count, 1)
票数 26
EN

Stack Overflow用户

发布于 2015-09-28 20:38:32

您可以通过像这样在ModelSignal上模拟django.db.models.signals.py类来模拟django信号:

代码语言:javascript
复制
@patch("django.db.models.signals.ModelSignal.send")
def test_overwhelming(self, mocker_signal):
    obj = Object()

这应该能起作用。请注意,这将模拟所有信号,无论您使用的是哪个对象。

如果您可能会使用mocker库,则可以这样做:

代码语言:javascript
复制
from mocker import Mocker, ARGS, KWARGS

def test_overwhelming(self):
    mocker = Mocker()
    # mock the post save signal
    msave = mocker.replace("django.db.models.signals")
    msave.post_save.send(KWARGS)
    mocker.count(0, None)

    with mocker:
        obj = Object()

这是更多的线条,但效果也很好:)

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13112302

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档