使用 pytest-mock 检查调用顺序
Checking call order with pytest-mock
在下面显示的代码片段中,我想测试 run()
函数中的函数调用顺序,即 f_3
在 f_2
之后调用,在 f_2
之后调用14=]:
class TestMock:
def f_1(self) -> None:
pass
def f_2(self) -> None:
pass
def f_3(self) -> None:
pass
def run(self) -> None:
self.f_1()
self.f_2()
self.f_3()
有什么方法可以使用 pytest-mock
做到这一点吗?我试图在我的测试文件中模拟 f_1
、f_2
和 f_3
函数,并将 assert_has_calls
与 any_order=False
一起使用,但是没有成功。
提前感谢您的帮助或提示!
最好的,
阿列克谢
您在 any_order=False
方面走在了正确的轨道上,您只需要了解 attach_mock
功能:
import yourmodule
def test_something(mocker):
mock = mocker.MagicMock()
mock.attach_mock(mocker.patch("yourmodule.TestMock.f_1"), "f_1")
mock.attach_mock(mocker.patch("yourmodule.TestMock.f_2"), "f_2")
mock.attach_mock(mocker.patch("yourmodule.TestMock.f_3"), "f_3")
yourinstance = yourmodule.TestMock()
yourinstance.run()
mock.assert_has_calls(
[
mocker.call.f_1(),
mocker.call.f_2(),
mocker.call.f_3(),
],
any_order=False,
)
我已经完全切换到 unittest.mock
并且现在有以下工作代码:
@mock.patch('.'.join([__name__, 'TestMock', 'f_3']))
@mock.patch('.'.join([__name__, 'TestMock', 'f_2']))
@mock.patch('.'.join([__name__, 'TestMock', 'f_1']))
def test_order_2(f_1: mock.NonCallableMock,
f_2: mock.NonCallableMock,
f_3: mock.NonCallableMock) -> None:
manager = mock.Mock()
manager.attach_mock(f_1, 'f_1')
manager.attach_mock(f_2, 'f_2')
manager.attach_mock(f_3, 'f_3')
obj = TestMock()
obj.run()
manager.assert_has_calls([mock.call.f_1,
mock.call.f_2,
mock.call.f_3], any_order=False)
这里出现了问题:我不太理解属性名称背后的含义,所以它们是强制性的,但对我来说唯一合理的名称是函数名称本身。 .. 我修改了属性名称如下:
@mock.patch('.'.join([__name__, 'TestMock', 'f_3']))
@mock.patch('.'.join([__name__, 'TestMock', 'f_2']))
@mock.patch('.'.join([__name__, 'TestMock', 'f_1']))
def test_order_1(f_1: mock.NonCallableMock,
f_2: mock.NonCallableMock,
f_3: mock.NonCallableMock) -> None:
manager = mock.Mock()
manager.attach_mock(f_1, f_1._extract_mock_name())
manager.attach_mock(f_2, f_2._extract_mock_name())
manager.attach_mock(f_3, f_3._extract_mock_name())
obj = TestMock()
obj.run()
manager.assert_has_calls([mock.call.f_1,
mock.call.f_2,
mock.call.f_3], any_order=False)
很高兴听到您对此的意见!
顺便问一下,为什么 f_*
模拟对象是 mock.NonCallableMoc
类型?我希望它们被虚拟函数取代 (Collable
)...
再次感谢您的帮助!
最好的,
阿列克谢
在下面显示的代码片段中,我想测试 run()
函数中的函数调用顺序,即 f_3
在 f_2
之后调用,在 f_2
之后调用14=]:
class TestMock:
def f_1(self) -> None:
pass
def f_2(self) -> None:
pass
def f_3(self) -> None:
pass
def run(self) -> None:
self.f_1()
self.f_2()
self.f_3()
有什么方法可以使用 pytest-mock
做到这一点吗?我试图在我的测试文件中模拟 f_1
、f_2
和 f_3
函数,并将 assert_has_calls
与 any_order=False
一起使用,但是没有成功。
提前感谢您的帮助或提示!
最好的, 阿列克谢
您在 any_order=False
方面走在了正确的轨道上,您只需要了解 attach_mock
功能:
import yourmodule
def test_something(mocker):
mock = mocker.MagicMock()
mock.attach_mock(mocker.patch("yourmodule.TestMock.f_1"), "f_1")
mock.attach_mock(mocker.patch("yourmodule.TestMock.f_2"), "f_2")
mock.attach_mock(mocker.patch("yourmodule.TestMock.f_3"), "f_3")
yourinstance = yourmodule.TestMock()
yourinstance.run()
mock.assert_has_calls(
[
mocker.call.f_1(),
mocker.call.f_2(),
mocker.call.f_3(),
],
any_order=False,
)
我已经完全切换到 unittest.mock
并且现在有以下工作代码:
@mock.patch('.'.join([__name__, 'TestMock', 'f_3']))
@mock.patch('.'.join([__name__, 'TestMock', 'f_2']))
@mock.patch('.'.join([__name__, 'TestMock', 'f_1']))
def test_order_2(f_1: mock.NonCallableMock,
f_2: mock.NonCallableMock,
f_3: mock.NonCallableMock) -> None:
manager = mock.Mock()
manager.attach_mock(f_1, 'f_1')
manager.attach_mock(f_2, 'f_2')
manager.attach_mock(f_3, 'f_3')
obj = TestMock()
obj.run()
manager.assert_has_calls([mock.call.f_1,
mock.call.f_2,
mock.call.f_3], any_order=False)
这里出现了问题:我不太理解属性名称背后的含义,所以它们是强制性的,但对我来说唯一合理的名称是函数名称本身。 .. 我修改了属性名称如下:
@mock.patch('.'.join([__name__, 'TestMock', 'f_3']))
@mock.patch('.'.join([__name__, 'TestMock', 'f_2']))
@mock.patch('.'.join([__name__, 'TestMock', 'f_1']))
def test_order_1(f_1: mock.NonCallableMock,
f_2: mock.NonCallableMock,
f_3: mock.NonCallableMock) -> None:
manager = mock.Mock()
manager.attach_mock(f_1, f_1._extract_mock_name())
manager.attach_mock(f_2, f_2._extract_mock_name())
manager.attach_mock(f_3, f_3._extract_mock_name())
obj = TestMock()
obj.run()
manager.assert_has_calls([mock.call.f_1,
mock.call.f_2,
mock.call.f_3], any_order=False)
很高兴听到您对此的意见!
顺便问一下,为什么 f_*
模拟对象是 mock.NonCallableMoc
类型?我希望它们被虚拟函数取代 (Collable
)...
再次感谢您的帮助!
最好的, 阿列克谢