我有一个 python 文件说
python_file_a.py
def load_content():
dir = "/down/model/"
model = Model(model_dir=dir)
return model
model = load_content()
def invoke(req):
return model.execute(req)
test_python_file_a.py
@patch("module.python_file_a.load_content")
@patch("module.python_file_a.model", Mock(spec=Model))
def test_invoke():
from module.python_file_a import model, invoke
model.execute = Mock(return_value="Some response")
invoke("some request")
这还是在测试中尝试从路径“/down/model/”加载实际模型。什么是正确的修补方法,以便在测试中模拟 load_content
函数?
答案 0 :(得分:0)
如果不了解更多关于您的代码的作用或使用方式的信息,就很难说清楚,但在这种情况下,正确的方法 - 在许多情况下 - 是不要将值硬编码为函数中的局部变量。更改您的 load_content()
函数以采用如下参数:
def load_content(dirname):
...
甚至给它一个像
这样的默认值def load_content(dirname="/default/path"):
pass
对于测试,不要使用在模块级别实例化的 model
实例(可以说您一开始不应该这样做,但这同样取决于您要尝试做什么)。>
更新:仔细检查后,问题似乎确实源于您在导入时实例化模块全局实例。也许尽量避免这样做,而是使用延迟实例化,例如:
model = None
那么如果你真的必须写一个访问全局变量的函数:
def invoke():
global model
if model is None:
model = load_content()
或者,您可以使用 PEP 562 模块级 __getattr__
函数。
或者编写一个类,而不是将所有内容都放在模块级别。
class ModelInvoker:
def __init__(self, dirname='/path/to/content'):
self.dirname = dirname
@functools.cached_property
def model(self):
return load_content(self.dirname)
def invoke(self, req):
return model.execute(req)
许多其他方法取决于您的用例。但是,如果您希望能够轻松地模拟和替换某些代码的一部分,并且不想在导入时不必要地执行代码,那么您需要找到某种形式的封装。