Automate testing a function using MagicMock to mock a dependency
Preconditions (2)
✅ Expected Result: The test passes confirming 'get_data' returns the mocked data and 'fetch_api_data' was called once.
from unittest.mock import MagicMock, patch import pytest # Module code to test def fetch_api_data(): # Imagine this calls an external API return {'real': 'data'} def get_data(): return fetch_api_data() # Test code def test_get_data_with_mock(): with patch('__main__.fetch_api_data', new=MagicMock(return_value={'key': 'value'})) as mock_fetch: result = get_data() assert result == {'key': 'value'}, f"Expected mocked data, got {result}" mock_fetch.assert_called_once()
The test uses patch as a context manager to replace fetch_api_data with a MagicMock that returns a fixed dictionary.
Calling get_data() then returns the mocked data instead of calling the real API.
Assertions check that the returned data matches the mock and that the mocked function was called exactly once.
This keeps the test isolated and fast without real API calls.
Now add data-driven testing with 3 different mocked return values for 'fetch_api_data' and verify 'get_data' returns each correctly.
Mock and MagicMock in pytest?Mock creates fake objects for testing, but does not automatically support Python's special methods like __len__ or __getitem__.MagicMock extends Mock by including default implementations for many special methods, making it useful when those methods are called during tests.MagicMock supports special methods like __len__ and __getitem__, Mock does not. -> Option AMagicMock object in pytest?MagicMock().MagicMock is a class, so MagicMock() creates a new mock object. The other options use invalid syntax for instantiation.from unittest.mock import MagicMock mock = MagicMock() mock.__len__.return_value = 5 print(len(mock))
mock.__len__.return_value = 5 tells the mock to return 5 when len() is called on it, because len() calls the __len__ method.print(len(mock))__len__ is mocked to return 5, len(mock) will print 5.from unittest.mock import Mock mock = Mock() mock.__getitem__.return_value = 'value' print(mock[0])
Mock does not implement special methods like __getitem__ automatically, so setting mock.__getitem__.return_value has no effect on indexing.mock[0] calls __getitem__, but since Mock does not handle it, this raises a TypeError. To mock indexing, use MagicMock.obj.__str__() internally. Which mock object and setup will correctly simulate str(obj) returning 'mocked string'?str(obj) call internally uses the __str__ method, which is a special method.MagicMock supports special methods like __str__. Setting mock.__str__.return_value = 'mocked string' makes str(mock) return 'mocked string'.mock = Mock() and set mock.__str__ = lambda: 'mocked string' uses Mock which does not support special methods by default. Options C and D use incorrect attribute names or types.mock = MagicMock() and set mock.__str__.return_value = 'mocked string' -> Option DPass the test and this pattern moves unknown