如何在python中模拟并仍然允许执行模拟函数的实际代码

dow*_*123 6 python django patch pytest python-mock

我最近开始在 python 中使用模拟框架。似乎如果我修补一个函数,则不会调用实际代码-这意味着未实现此实际函数所做的数据库更改等。我一直试图通过事先调用函数并存储返回值并将其作为 arg 传递到 patch() 来绕过它,但是有没有更好的方法来做到这一点?理想情况下,我想要一个可以用作 a 的代码,silent observer我可以简单地询问它是否observed调用了某个函数,调用了多少次,以及使用了哪些参数

我当前的代码

return_val = funct()

# C: Now call me again and assert that these intensive computation functions are not called but taken from cache
with patch('funct', return_value=return_val) as mock_task:

    me_response = self.client.get(me_url, format='json')    #should fetch from cache
    assert not mock_task.called
Run Code Online (Sandbox Code Playgroud)

log*_*nes 5

要模拟调用的方法,您应该使用wraps关键字。考虑以下:

class Foo(object):

    def do_thing(self, a):
        print("A: %s" % a)
        self._do_private_thing(a)

    def _do_private_thing(self, a):
        print("PRIVATE STUFF HAPPENING.")
        print("A: %s" % a)
Run Code Online (Sandbox Code Playgroud)

然后在你的测试中,你会有类似的东西:

import mock
a = Foo()
with mock.patch.object(a, '_do_private_thing', wraps=a._do_private_thing) as private_mock:
    a.do_thing("lol")
    private_mock.assert_called_with("lol")
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。

  • 是否可以在不初始化类“Foo()”的情况下执行相同的操作? (6认同)

l__*_*__l 5

您可以将该Mock#side_effect属性设置为您的原始函数。

orig = funct
funct = Mock(side_effect=orig)
Run Code Online (Sandbox Code Playgroud)

我确实发现 loganasherjones 的答案更优雅。

只是为那些可能需要它的人添加另一种可能性。