如果您使用新类 Mock 修补了 thirdparty.Class,那么这意味着在源代码中实例化 thirdparty.Class 的所有调用都将使用 Mock。
解决方案 1
为了能够注入夹具file 以在Mock 类中使用,您必须在Mock 类可以访问的某个位置定义它。您无法从__init__ 控制它,因为它将从源代码中调用。您可以做的是将该类 Mock 放入函数或夹具中,然后将 file 作为函数/夹具本身中的变量访问。
thirdparty.py
class MyClass:
def __init__(self, file):
self._file = file
def get(self, *args, **kwargs):
return self._file
def func():
obj = MyClass("/path/to/real")
file = obj.get()
print("File to process:", file)
return file
test_thirdparty.py
from unittest.mock import patch
import pytest
from thirdparty import func
@pytest.fixture(scope="session")
def file():
return "/path/to/mock"
@pytest.fixture
def my_mock_class(file): # This can also be an ordinary function (not a fixture). You just need to pass the <file>.
class MyMockClass:
def __init__(self, *args, **kwargs):
self._file = file # Ignore the entered file in the initialization (__init__). Instead, read the injected file from the current fixture itself (my_mock_class).
def get(self, *args, **kwargs):
return self._file
return MyMockClass
def test_real_file():
assert func() == "/path/to/real"
def test_mock_file(my_mock_class):
with patch("thirdparty.MyClass", new=my_mock_class):
assert func() == "/path/to/mock"
输出
$ pytest -q -rP
.. [100%]
=============================== PASSES ===============================
___________________________ test_real_file ___________________________
------------------------ Captured stdout call ------------------------
File to process: /path/to/real
___________________________ test_mock_file ___________________________
------------------------ Captured stdout call ------------------------
File to process: /path/to/mock
2 passed in 0.05s
解决方案 2
在源代码中,找到实例化它的那些:
the_class = thirdparty.Class(some_file)
然后,跟踪some_file 的创建位置。假设这是来自函数调用:
some_file = get_file()
然后,您需要修补 get_file() 如何返回夹具 file 的值,以便在创建 thirdparty.Class(或者更确切地说是 Mock,因为我们已经修补它)时,self._file 的值将是夹具中的那个。
mocker.patch('get_file", return_value=file) # Where <file> is the fixture