Reputation: 13
Let's say I have a simplified class Object
:
class Object:
def __init__(self, data):
self.data = data
def get_data():
return data.copy()
And freestanding function foo
:
def foo(obj: Object):
copied_data = obj.get_data()
...
I want to test foo
and use a fixture with mocked Object
instance to pass as the argument to foo
. I want the mocked object to return some predefined data so I need to mock its method as well.
How should I do this in a "proper" way with pytest? I'm not sure how to combine mocks and fixtures.
Upvotes: 1
Views: 7059
Reputation: 10699
Using the with statement and the sample patching documentations:
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' ...
We can use patch() inside a fixture and then yield the mocked instance.
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'
Output:
$ 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
and define the return value of its methods.Upvotes: 3