繁体   English   中英

在有和没有pytest-mock的情况下模拟标准库函数

[英]Mocking a Standard Library function with and without pytest-mock

为了进行测试,我想模拟shutil.which(Python 3.5.1),该方法在简化方法find_foo()中调用

def _find_foo(self) -> Path:
foo_exe = which('foo', path=None)
if foo_exe:
    return Path(foo_exe)
else:
    return None

我正在使用pytest来实现我的测试用例。 因此,我也想使用pytest扩展名pytest-mock。 在下面,我使用pytest + pytest-mock粘贴了一个示例测试用例:

def test_find_foo(mocker):
    mocker.patch('shutil.which', return_value = '/path/foo.exe')

    foo_path = find_foo()
    assert foo_path is '/path/foo.exe'

用pytest-mock模拟的这种方式不起作用。 shutil。仍然被调用而不是模拟

我试图直接使用现在是Python3一部分的模拟包:

def test_find_foo():
    with unittest.mock.patch('shutil.which') as patched_which:
        patched_which.return_value = '/path/foo.exe'

        foo_path = find_foo()
        assert foo_path is '/path/foo.exe'

可悲的是结果是一样的。 还会shutil.which()而不是指定的模拟。

在我的测试案例中,成功实现模拟的哪些步骤是错误的或错过了?

我花了更多时间研究unittest.mock和pytest-mock。 我找到了一个简单的解决方案,而没有使用补丁装饰器修改生产代码。 在下面的代码中,我粘贴了一段代码,演示了pytest-mock的第三种方法:

def test_find_foo(mocker):
    mocker.patch('__main__.which', return_value='/path/foo.exe')

    foo_path = find_foo()
    assert foo_path == Path('/path/foo.exe')

如果没有pytest-mock(普通的unittest-mock和@patch装饰器),此解决方案也可以工作。 上面的代码片段中的重要一行是

mocker.patch('__main__.which', return_value='/path/foo.exe')

修补程序装饰程序需要从测试中的系统调用的功能名称 (完整路径)。 模拟文档中对此进行了明确说明。 以下段落总结了补丁装饰器的这一原理:

修补程序通过(临时)将名称指向的对象更改为另一个对象来工作。 可以有许多名称指向任何单个对象,因此要使修补程序起作用,必须确保修补受测系统使用的名称。

尝试使用monkeypatch 您可以在示例中看到它们如何“ monkeypatch” os.getcwd返回所需的路径。 在您的情况下,我认为这应该可行:

 monkeypatch.setattr("shutil.which", lambda: "/path/foo.exe")

which方法注入到您的方法或对象中将使您可以在没有pytest-mock情况下模拟依赖pytest-mock

def _find_foo(self, which_fn=shutil.which) -> Path:
  foo_exe = which_fn('foo', path=None)
  if foo_exe:
      return Path(foo_exe)
  else:
      return None


def test_find_foo():
   mock_which = Mock(return_value = '/path/foo.exe')

   foo_path = obj._find_foo(which_fn=mock_which)
   assert foo_path is '/path/foo.exe'

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM