确保不要使用unittest.mock.Mock,而是使用unittest.mock.MagicMock,原因是here。你可以关注这个关于Mocking Classes的文档(所有这些都将使用MagicMock)。
对于您的情况,这里有 3 个选项来模拟 load_plugin() 返回的对象。您可以选择最适合您的需求。
-
mock_plugin_return_values - 通过 return_value 模拟
-
mock_plugin_side_effect - 通过 side_effect 模拟
-
mock_plugin_stub - 通过存根类进行模拟
文件树
.
├── folder
│ ├── layer
│ │ └── base.py
│ ├── plugin.py
│ └── tileindex
│ └── base.py
└── tests
└── test_layer.py
文件夹/层/base.py
from folder.plugin import load_plugin
class BaseLayer:
def __init__(self):
self.tileindex = load_plugin()
def somefunction(self):
a = self.tileindex.add("a")
print("add:", a)
key = self.tileindex.get_key("a")
print("get_key:", key)
r = self.tileindex.bulk_add([1, 2, 3])
print("bulk_add:", r)
status = r['identifier']
print("status:", status)
return a, key, r, status
文件夹/plugin.py
from folder.tileindex.base import SomePlugin
def load_plugin():
return SomePlugin()
文件夹/tileindex/base.py
class SomePlugin():
pass
test/test_layer.py
import pytest
from folder.layer.base import BaseLayer
# Note, this requires <pip install pytest-mock>
@pytest.fixture
def mock_plugin_return_values(mocker):
mock_cls = mocker.patch("folder.plugin.SomePlugin")
mock_obj = mock_cls.return_value
mock_obj.add.return_value = "Anything!"
mock_obj.get_key.return_value = "Something!"
mock_obj.bulk_add.return_value = {"identifier": "Nothing!"}
@pytest.fixture
def mock_plugin_side_effect(mocker):
mock_cls = mocker.patch("folder.plugin.SomePlugin")
mock_obj = mock_cls.return_value
mock_obj.add.side_effect = lambda arg: f"Adding {arg} here"
mock_obj.get_key.side_effect = lambda arg: f"Getting {arg} now"
mock_obj.bulk_add.side_effect = lambda arg: {"identifier": f"Adding the {len(arg)} elements"}
@pytest.fixture
def mock_plugin_stub(mocker):
# Option 1: Create a new class
# class SomePluginStub:
# Option 2: Inehrit from the actual class and just override the functions to mock
from folder.tileindex.base import SomePlugin
class SomePluginStub(SomePlugin):
def add(self, arg):
return f"Adding {arg} here"
def get_key(self, arg):
return f"Getting {arg} now"
def bulk_add(self, arg):
return {"identifier": f"Adding the {len(arg)} elements"}
mocker.patch("folder.plugin.SomePlugin", SomePluginStub)
def test_return_values(mock_plugin_return_values):
layer = BaseLayer()
result = layer.somefunction()
print(result)
assert result == ('Anything!', 'Something!', {'identifier': 'Nothing!'}, 'Nothing!')
def test_side_effect(mock_plugin_side_effect):
layer = BaseLayer()
result = layer.somefunction()
print(result)
assert result == ('Adding a here', 'Getting a now', {'identifier': 'Adding the 3 elements'}, 'Adding the 3 elements')
def test_stub(mock_plugin_stub):
layer = BaseLayer()
result = layer.somefunction()
print(result)
assert result == ('Adding a here', 'Getting a now', {'identifier': 'Adding the 3 elements'}, 'Adding the 3 elements')
输出
$ pytest -q -rP
... [100%]
=========================================== PASSES ============================================
_____________________________________ test_return_values ______________________________________
------------------------------------ Captured stdout call -------------------------------------
add: Anything!
get_key: Something!
bulk_add: {'identifier': 'Nothing!'}
status: Nothing!
('Anything!', 'Something!', {'identifier': 'Nothing!'}, 'Nothing!')
______________________________________ test_side_effect _______________________________________
------------------------------------ Captured stdout call -------------------------------------
add: Adding a here
get_key: Getting a now
bulk_add: {'identifier': 'Adding the 3 elements'}
status: Adding the 3 elements
('Adding a here', 'Getting a now', {'identifier': 'Adding the 3 elements'}, 'Adding the 3 elements')
__________________________________________ test_stub __________________________________________
------------------------------------ Captured stdout call -------------------------------------
add: Adding a here
get_key: Getting a now
bulk_add: {'identifier': 'Adding the 3 elements'}
status: Adding the 3 elements
('Adding a here', 'Getting a now', {'identifier': 'Adding the 3 elements'}, 'Adding the 3 elements')
3 passed in 0.06s