Python3 模拟用另一个函数替换函数

Dan*_*ats 5 python unit-testing mocking

如何使用 python 中的另一个函数来模拟一个函数,这也将提供一个模拟对象?

我有执行类似操作的代码:

def foo(arg1, arg2):
    r = bar(arg1)
    # does interesting things
Run Code Online (Sandbox Code Playgroud)

我想替换bar函数的实现,让它返回合理的值,并确保使用正确的参数调用它。

我试过这个,fake_bar我的简单替代品在哪里bar

from unittest.mock import patch

def test_foo():
   with patch("x.bar", fake_bar) as mock_bar:
      actual = foo(arg1, arg2)
      assert actual == expected
      mock_bar.assert_called_once_with(arg1)
Run Code Online (Sandbox Code Playgroud)

但是,我收到此错误:

AttributeError: 'function' 对象没有属性 'assert_called_once'

我发现这个问题建议使用 create_autospec。但是, mock.create_autospec 不保留返回值。

Python文档建议做这样的事情:

mock_function = create_autospec(function, return_value='fishy')
Run Code Online (Sandbox Code Playgroud)

但是,我的伪造版本bar计算出的返回值不是静态的,也不是那么容易放入内联 lambda 中。

我觉得我错过了一些明显的东西。有没有一种方法可以轻松地模拟一个函数并用比静态返回值更复杂的东西替换它的实现?

che*_*ner 10

使用wraps关键字参数:

def test_foo():
   with patch("x.bar", wraps=fake_bar) as mock_bar:
      actual = foo(arg1, arg2)
      assert actual == expected
      mock_bar.assert_called_once_with(arg1)
Run Code Online (Sandbox Code Playgroud)

此处x.bar是您要替换的函数的完全限定名称,例如“bigbusiness.account.AccountRepository.insert”。

mock_bar仍将是 a Mock(默认情况下),但这Mock将包装 function fake_bar,因此 的返回值mock_bar是 的返回值fake_bar,而不是另一个Mock实例。

  • 很好,我在文档中只发现一行提到了这一点,但没有任何示例 (4认同)
  • 您能否显示 fake_bar 的定义以使这个答案更完整一点? (3认同)