Pytest 适用于旧的模拟,但不适用于 unittest.mock [英] Pytest works with old mock, but not unittest.mock
问题描述
我正在将一些代码从 Python 2 移植到 3,并且 py.test
与 unittest.mock<的
patch
装饰器不能很好地配合使用代码>.当我使用 patch
装饰器将模拟传递给测试函数的参数时,py.test
反而将该参数解释为夹具,并且无法设置测试.
I'm porting some code from Python 2 to 3, and py.test
isn't playing well with the patch
decorator from unittest.mock
. When I use the patch
decorator to pass a mock into the arguments of a test function, py.test
instead interprets that argument to be a fixture, and is unable to set up the test.
这是一个人为的例子,希望能说明问题:
Here's a contrived example that hopefully illuminates the problem:
@patch('my_module.my_func')
def test_my_func(mock_func):
mock_func()
mock_func.assert_called_once_with()
运行py.test
后,错误信息如下:
After running py.test
, the error message would look like:
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
导入补丁,没有错误.
This is the only scenario under which this failure occurs. If I explicitly call the test (i.e. run test_my_func()
), no error. If I patch my_func
using either of the other patching techniques, no error. If I import patch from mock
instead of unittest.mock
, no error.
只有在使用 py.test
、使用 unittest.mock
运行我的测试时,并在发生这种情况时使用装饰器进行修补.
It's only while running my tests using py.test
, using unittest.mock
, and patching using the decorator when this occurs.
我正在运行 Python 3.4.5.
I'm running Python 3.4.5.
推荐答案
是的,不支持模拟装饰器.这还不错——通过装饰器设备更改函数签名被认为是个坏主意.但是你仍然可以使用 和 mock.patch(...)
语法.
Yes, mock decorators are not supported.
It's not such bad -- changing function signature by decorator appliance is considered as bad idea.
But you still may use with mock.patch(...)
syntax.
还有一个选项是 pytest-mock 插件,带有非常干净的 api 用于模拟:
Also as an option there is pytest-mock plugin with pretty clean api for mocking:
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')
这篇关于Pytest 适用于旧的模拟,但不适用于 unittest.mock的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!