Pytest适用于旧的mock,但不适用于unittest.mock

时间:2016-08-26 15:16:22

标签: python unit-testing python-3.x mocking pytest

我正在将一些代码从Python 2移植到3,并且py.testpatch的{​​{1}}装饰器不兼容。当我使用unittest.mock装饰器将模拟传递给测试函数的参数时,patch会将该参数解释为一个装置,并且无法设置测试。

这是一个人为的例子,希望能够解决这个问题:

py.test

运行@patch('my_module.my_func') def test_my_func(mock_func): mock_func() mock_func.assert_called_once_with() 后,错误消息如下所示:

py.test

这是发生此故障的唯一方案。如果我明确地调用测试(即运行E fixture 'my_func' not found > available fixtures: cache, capfd, capsys, doctest_namespace, monkeypatch, pytestconfig, record_xml_property, recwarn, tmpdir, tmpdir_factory > use 'pytest --fixtures [testpath]' for help on them. ),则没有错误。如果我使用其他任何修补技术修补test_my_func(),则没有错误。如果我从my_func而不是mock导入补丁,则不会出现错误。

仅在使用unittest.mock运行我的测试时,使用py.test,并在发生这种情况时使用装饰器进行修补。

我正在运行Python 3.4.5。

2 个答案:

答案 0 :(得分:8)

是的,不支持模拟装饰器。 它并不是那么糟糕 - 装饰设备改变功能签名被认为是个坏主意。 但您仍然可以使用with mock.patch(...)语法。

另外作为一个选项,有pytest-mock插件,非常干净的api用于模拟:

def test_foo(mocker):
    # all valid calls
    mocker.patch('os.remove')
    mocker.patch.object(os, 'listdir', autospec=True)
    mocked_isfile = mocker.patch('os.path.isfile')

答案 1 :(得分:0)

有一个pytest问题,现在似乎可以在pytest的较新版本中解决: https://github.com/pytest-dev/pytest/pull/3206/commits/b6166dccb4d2b48173aa7e7739be52db9d2d56a0

基本上,如果您安装了mock,这将失败。您可以通过卸载mock并再次运行测试来进行验证。

如果您确实需要该版本的pytest,则可以在函数内使用with patch(..)来获得模拟。