检查在测试期间是否调用了一次 pytest fixture
Check if pytest fixture is called once during testing
pytest
是否提供类似 unittest.mock
的功能来检查 mock 是否实际被调用一次(或使用某个参数调用一次)?
示例源代码:
my_package/my_module.py
from com.abc.validation import Validation
class MyModule:
def __init__(self):
pass
def will_call_other_package(self):
val = Validation()
val.do()
def run(self):
self.will_call_other_package()
上述源代码的示例测试代码:
test_my_module.py
import pytest
from pytest_mock import mocker
from my_package.my_module import MyModule
@pytest.fixture
def mock_will_call_other_package(mocker):
mocker.patch('my_package.my_module.will_call_other_package')
@pytest.mark.usefixtures("mock_will_call_other_package")
class TestMyModule:
def test_run(self):
MyModule().run()
#check `will_call_other_package` method is called.
#Looking for something similar to what unittest.mock provide
#mock_will_call_other_package.called_once
你可以试试这个:
import pytest
from my_package.my_module import MyModule
def test_run(mocker):
mocker.patch('my_package.my_module.will_call_other_package')
MyModule().run()
mock_will_call_other_package.assert_called_once()
如果要使用进行修补的夹具,可以将修补移动到夹具中:
import pytest
from unittest import mock
from my_package.my_module import MyModule
@pytest.fixture
def mock_will_call_other_package():
with mock.patch('my_package.my_module.will_call_other_package') as mocked:
yield mocked
# the mocking will be reverted here, e.g. after the test
class TestMyModule:
def test_run(self, mock_will_call_other_package):
MyModule().run()
mock_will_call_other_package.assert_called_once()
注意在测试中必须使用fixture参数。仅使用 @pytest.mark.usefixtures
不会让您访问模拟本身。如果您不需要在所有测试中访问模拟(或在夹具中使用 autouse=True
),您仍然可以使用它在 class 中的所有测试中有效。
另请注意,您在这里不需要 pytest-mock
- 但正如@hoefling 所提到的,使用它可以使夹具更具可读性,因为您不需要 with
子句:
@pytest.fixture
def mock_will_call_other_package(mocker):
yield mocker.patch('my_package.my_module.will_call_other_package')
顺便说一句:您不需要导入 mocker
。夹具按名称查找,如果安装了相应的插件,则自动可用。
首先,您可能不需要 pytest_mock
等外部库的负担,因为 pytest
已经让您使用 integration with unittest。
您也不需要使用 usefixtures
因为无论何时您需要一个固定装置,您只需在您的测试方法中接收它。
基于您自己的代码的理想场景与此类似:
import pytest
from unittest.mock import patch
from com.abc.validation import Validation
class MyModule:
def __init__(self):
pass
def will_call_other_package(self):
val = Validation()
val.do()
def run(self):
self.will_call_other_package()
@pytest.fixture
def call_other_module():
with patch("my_package.my_module.MyModule.will_call_other_package") as _patched:
yield _patched
class TestMyModule:
def test_run_will_call_other_package(self, call_other_module):
call_other_module.assert_not_called()
obj = MyModule()
call_other_module.assert_not_called()
obj.run()
call_other_module.assert_called_once()
此外,如果您想确保您确实修补了目标 MyModule.will_call_other_package
,请像这样修改您的测试:
class TestMyModule:
def test_run_will_call_other_package(self, call_other_module):
call_other_module.assert_not_called()
obj = MyModule()
call_other_module.assert_not_called()
obj.run()
call_other_module.assert_called_once()
assert False, (MyModule.will_call_other_package, call_other_module)
你会看到类似这样的东西:
AssertionError: (<MagicMock name='will_call_other_package' id='140695551841328'>, <MagicMock name='will_call_other_package' id='140695551841328'>)
如你所见,两个对象的 id
是相同的,证明我们的实验是成功的。
pytest
是否提供类似 unittest.mock
的功能来检查 mock 是否实际被调用一次(或使用某个参数调用一次)?
示例源代码:
my_package/my_module.py
from com.abc.validation import Validation
class MyModule:
def __init__(self):
pass
def will_call_other_package(self):
val = Validation()
val.do()
def run(self):
self.will_call_other_package()
上述源代码的示例测试代码:
test_my_module.py
import pytest
from pytest_mock import mocker
from my_package.my_module import MyModule
@pytest.fixture
def mock_will_call_other_package(mocker):
mocker.patch('my_package.my_module.will_call_other_package')
@pytest.mark.usefixtures("mock_will_call_other_package")
class TestMyModule:
def test_run(self):
MyModule().run()
#check `will_call_other_package` method is called.
#Looking for something similar to what unittest.mock provide
#mock_will_call_other_package.called_once
你可以试试这个:
import pytest
from my_package.my_module import MyModule
def test_run(mocker):
mocker.patch('my_package.my_module.will_call_other_package')
MyModule().run()
mock_will_call_other_package.assert_called_once()
如果要使用进行修补的夹具,可以将修补移动到夹具中:
import pytest
from unittest import mock
from my_package.my_module import MyModule
@pytest.fixture
def mock_will_call_other_package():
with mock.patch('my_package.my_module.will_call_other_package') as mocked:
yield mocked
# the mocking will be reverted here, e.g. after the test
class TestMyModule:
def test_run(self, mock_will_call_other_package):
MyModule().run()
mock_will_call_other_package.assert_called_once()
注意在测试中必须使用fixture参数。仅使用 @pytest.mark.usefixtures
不会让您访问模拟本身。如果您不需要在所有测试中访问模拟(或在夹具中使用 autouse=True
),您仍然可以使用它在 class 中的所有测试中有效。
另请注意,您在这里不需要 pytest-mock
- 但正如@hoefling 所提到的,使用它可以使夹具更具可读性,因为您不需要 with
子句:
@pytest.fixture
def mock_will_call_other_package(mocker):
yield mocker.patch('my_package.my_module.will_call_other_package')
顺便说一句:您不需要导入 mocker
。夹具按名称查找,如果安装了相应的插件,则自动可用。
首先,您可能不需要 pytest_mock
等外部库的负担,因为 pytest
已经让您使用 integration with unittest。
您也不需要使用 usefixtures
因为无论何时您需要一个固定装置,您只需在您的测试方法中接收它。
基于您自己的代码的理想场景与此类似:
import pytest
from unittest.mock import patch
from com.abc.validation import Validation
class MyModule:
def __init__(self):
pass
def will_call_other_package(self):
val = Validation()
val.do()
def run(self):
self.will_call_other_package()
@pytest.fixture
def call_other_module():
with patch("my_package.my_module.MyModule.will_call_other_package") as _patched:
yield _patched
class TestMyModule:
def test_run_will_call_other_package(self, call_other_module):
call_other_module.assert_not_called()
obj = MyModule()
call_other_module.assert_not_called()
obj.run()
call_other_module.assert_called_once()
此外,如果您想确保您确实修补了目标 MyModule.will_call_other_package
,请像这样修改您的测试:
class TestMyModule:
def test_run_will_call_other_package(self, call_other_module):
call_other_module.assert_not_called()
obj = MyModule()
call_other_module.assert_not_called()
obj.run()
call_other_module.assert_called_once()
assert False, (MyModule.will_call_other_package, call_other_module)
你会看到类似这样的东西:
AssertionError: (<MagicMock name='will_call_other_package' id='140695551841328'>, <MagicMock name='will_call_other_package' id='140695551841328'>)
如你所见,两个对象的 id
是相同的,证明我们的实验是成功的。