How to Use pytest-mock for Easy Mocking in Tests
Use
pytest-mock by adding the mocker fixture to your test function. Call mocker.patch() to replace objects or functions with mocks during the test, allowing you to control behavior and assert calls.Syntax
The pytest-mock plugin provides a mocker fixture to your test functions. Use mocker.patch(target, **kwargs) to replace the target (a string path to the object) with a mock object. You can then configure the mock or check how it was called.
- mocker.patch(target): Replaces the target with a mock.
- target: The full import path of the object to mock, e.g.,
'module.Class.method'. - kwargs: Optional arguments like
return_valueto set what the mock returns.
python
def test_example(mocker): mock_func = mocker.patch('module.function') mock_func.return_value = 42 import module result = module.function() assert result == 42 mock_func.assert_called_once()
Example
This example shows how to mock a function in a module to control its return value and verify it was called once during the test.
python
import pytest # Imagine this is in mymodule.py def get_data(): return 'real data' def process_data(): data = get_data() return f'Processed {data}' # Test file def test_process_data(mocker): mock_get = mocker.patch('mymodule.get_data', return_value='mocked data') from mymodule import process_data result = process_data() assert result == 'Processed mocked data' mock_get.assert_called_once()
Output
============================= test session starts ==============================
collected 1 item
test_example.py . [100%]
============================== 1 passed in 0.03s ===============================
Common Pitfalls
Common mistakes include patching the wrong import path, forgetting to use the mocker fixture, or not asserting mock calls properly.
Always patch the object where it is used, not where it is defined. For example, if moduleA imports functionB from moduleB, patch moduleA.functionB, not moduleB.functionB.
python
import pytest # Wrong patching - patching where function is defined, but test uses imported version def test_wrong_patch(mocker): mocker.patch('moduleB.functionB', return_value=1) # Wrong if test uses moduleA.functionB # Right patching def test_right_patch(mocker): mocker.patch('moduleA.functionB', return_value=1) # Correct if test uses moduleA.functionB
Quick Reference
- mocker.patch(target, return_value=val): Replace target with mock returning
val. - mock.assert_called_once(): Check mock was called exactly once.
- mock.assert_not_called(): Check mock was never called.
- mocker.spy(obj, 'method'): Spy on real method calls without replacing.
Key Takeaways
Use the pytest-mock
mocker fixture to patch objects easily in tests.Always patch the object where it is used, not where it is defined.
Configure mock return values with
return_value to control test behavior.Assert mock calls with methods like
assert_called_once() to verify interactions.Use
mocker.spy() to observe real method calls without replacing them.