Pytest - 模拟 class 实例作为参数传递
Pytest - mocking class instance passed as an argument
假设我有一个简化的 class Object
:
class Object:
def __init__(self, data):
self.data = data
def get_data():
return data.copy()
和独立函数foo
:
def foo(obj: Object):
copied_data = obj.get_data()
...
我想测试 foo
并使用带有模拟 Object
实例的夹具作为参数传递给 foo
。我希望模拟对象 return 一些预定义的数据,所以我也需要模拟它的方法。
我应该如何使用 pytest 以“正确”的方式执行此操作?我不确定如何组合模拟和固定装置。
使用 with statement and the sample patching 文档:
As well as a decorator patch()
can be used as a context manager in a with
statement:
...
>>> class Class:
... def method(self):
... pass
...
>>> with patch('__main__.Class') as MockClass:
... instance = MockClass.return_value
... instance.method.return_value = 'foo'
... assert Class() is instance
... assert Class().method() == 'foo'
...
我们可以使用 patch() inside a fixture and then yield 模拟实例。
src.py
class Object:
def __init__(self, data):
print("Real object initialized")
self.data = data
def get_data(self):
print("Real object get_data")
return self.data.copy()
def foo(obj: Object):
print("Object instance:", obj)
copied_data = obj.get_data()
return copied_data
test_src.py
from unittest.mock import patch
import pytest
from src import foo, Object
@pytest.fixture
def object_instance():
with patch('src.Object') as MockClass:
instance = MockClass.return_value
instance.get_data.return_value = 'bar'
yield instance
def test_real_impl():
object_instance = Object([1, 2])
assert foo(object_instance) == [1, 2]
def test_mock_impl(object_instance):
assert foo(object_instance) == 'bar'
输出:
$ pytest -q -rP
================================================================================================= PASSES ==================================================================================================
_____________________________________________________________________________________________ test_real_impl ______________________________________________________________________________________________
------------------------------------------------------------------------------------------ Captured stdout call -------------------------------------------------------------------------------------------
Real object initialized
Object instance: <src.Object object at 0x7fb59ef83820>
Real object get_data
_____________________________________________________________________________________________ test_mock_impl ______________________________________________________________________________________________
------------------------------------------------------------------------------------------ Captured stdout call -------------------------------------------------------------------------------------------
Object instance: <MagicMock name='Object()' id='140418032072736'>
2 passed in 0.06s
- 如您所见,我们能够创建一个模拟的
Object
并定义其方法的 return 值。
假设我有一个简化的 class Object
:
class Object:
def __init__(self, data):
self.data = data
def get_data():
return data.copy()
和独立函数foo
:
def foo(obj: Object):
copied_data = obj.get_data()
...
我想测试 foo
并使用带有模拟 Object
实例的夹具作为参数传递给 foo
。我希望模拟对象 return 一些预定义的数据,所以我也需要模拟它的方法。
我应该如何使用 pytest 以“正确”的方式执行此操作?我不确定如何组合模拟和固定装置。
使用 with statement and the sample patching 文档:
As well as a decorator
patch()
can be used as a context manager in awith
statement:...
>>> class Class: ... def method(self): ... pass ... >>> with patch('__main__.Class') as MockClass: ... instance = MockClass.return_value ... instance.method.return_value = 'foo' ... assert Class() is instance ... assert Class().method() == 'foo' ...
我们可以使用 patch() inside a fixture and then yield 模拟实例。
src.py
class Object:
def __init__(self, data):
print("Real object initialized")
self.data = data
def get_data(self):
print("Real object get_data")
return self.data.copy()
def foo(obj: Object):
print("Object instance:", obj)
copied_data = obj.get_data()
return copied_data
test_src.py
from unittest.mock import patch
import pytest
from src import foo, Object
@pytest.fixture
def object_instance():
with patch('src.Object') as MockClass:
instance = MockClass.return_value
instance.get_data.return_value = 'bar'
yield instance
def test_real_impl():
object_instance = Object([1, 2])
assert foo(object_instance) == [1, 2]
def test_mock_impl(object_instance):
assert foo(object_instance) == 'bar'
输出:
$ pytest -q -rP
================================================================================================= PASSES ==================================================================================================
_____________________________________________________________________________________________ test_real_impl ______________________________________________________________________________________________
------------------------------------------------------------------------------------------ Captured stdout call -------------------------------------------------------------------------------------------
Real object initialized
Object instance: <src.Object object at 0x7fb59ef83820>
Real object get_data
_____________________________________________________________________________________________ test_mock_impl ______________________________________________________________________________________________
------------------------------------------------------------------------------------------ Captured stdout call -------------------------------------------------------------------------------------------
Object instance: <MagicMock name='Object()' id='140418032072736'>
2 passed in 0.06s
- 如您所见,我们能够创建一个模拟的
Object
并定义其方法的 return 值。