π§ͺ Python Mocking & Stubbing β Simulate and Control Code Behavior in Tests
π§² Introduction β Why Use Mocking & Stubbing?
In unit testing, you often need to test a piece of code in isolation. But what if that code:
- Connects to a database?
- Makes HTTP calls?
- Depends on slow, external services?
This is where mocking and stubbing come in.
With Pythonβs built-in unittest.mock module, you can:
- Replace real objects with controlled stand-ins
- Simulate return values, exceptions, and side effects
- Verify how functions are called
π― In this guide, you’ll learn:
- The difference between mocking and stubbing
- How to use Mock,MagicMock, andpatch()
- How to simulate return values and exceptions
- Best practices and common pitfalls
β What Are Mocking and Stubbing?
| Term | Description | 
|---|---|
| Stub | A simplified version of a function that returns fixed output | 
| Mock | A fake object that records calls and can simulate complex behavior | 
π‘ Stubs are passive (just return data), while mocks are interactive (track usage).
π¦ Getting Started with unittest.mock
from unittest.mock import Mock
β Create a Simple Mock
mock_func = Mock()
mock_func.return_value = "Hello"
print(mock_func())  # Output: Hello
π§ Setting Return Values and Side Effects
mock = Mock()
mock.get_data.return_value = [1, 2, 3]
mock.raise_error.side_effect = ValueError("Invalid data")
print(mock.get_data())         # [1, 2, 3]
mock.raise_error()             # Raises ValueError
π MagicMock β Smarter Mocks with Built-in Magic Methods
from unittest.mock import MagicMock
m = MagicMock()
m.__len__.return_value = 5
print(len(m))  # 5
β
 MagicMock is a subclass of Mock with all dunder methods included.
π§ͺ Using patch() β Replace Objects Temporarily
β Replace a Method During Test
from unittest.mock import patch
def fetch_user():
    return "Real user data"
with patch('__main__.fetch_user', return_value="Mocked data"):
    print(fetch_user())  # Mocked data
print(fetch_user())      # Real user data
β
 patch() is perfect for mocking external dependencies, APIs, and class methods.
π οΈ Patching Objects Inside Classes
class EmailService:
    def send(self):
        return "Email sent"
with patch.object(EmailService, 'send', return_value="Mocked email"):
    service = EmailService()
    print(service.send())  # Mocked email
π§Ύ Verifying Calls and Arguments
β
 assert_called_with()
mock = Mock()
mock("Alice", 42)
mock.assert_called_with("Alice", 42)
β
 call_args, call_count, call_args_list
mock = Mock()
mock(1)
mock(2)
print(mock.call_count)          # 2
print(mock.call_args_list)      # [call(1), call(2)]
β Useful for verifying that functions were used correctly.
π§° Real-World Use Case β Mocking API Call
import requests
from unittest.mock import patch
def get_data():
    response = requests.get("https://api.example.com/data")
    return response.json()
@patch("requests.get")
def test_get_data(mock_get):
    mock_get.return_value.json.return_value = {"key": "value"}
    result = get_data()
    assert result == {"key": "value"}
π‘ No actual API request is madeβpure unit testing!
π§ Mocking vs Stubbing β Summary
| Feature | Stub | Mock | 
|---|---|---|
| Returns fixed data | β Yes | β Yes | 
| Tracks usage | β No | β
 Yes ( assert_called_with) | 
| Raises exceptions | β Yes | β
 Yes ( side_effect) | 
| Best for | Data setup | Behavior verification | 
π Best Practices
| β Do This | β Avoid This | 
|---|---|
| Use patch()as a context manager or decorator | Forgetting to stop the patch manually | 
| Verify arguments with assert_called_with() | Assuming mocks are always called | 
| Use side_effectfor exceptions or sequences | Hardcoding return values only | 
| Keep mocks focused on one behavior | Over-mocking everything | 
π Summary β Recap & Next Steps
Python’s unittest.mock gives you the power to test any part of your code in isolationβwithout relying on databases, APIs, or third-party services.
π Key Takeaways:
- β Use stubs for predictable outputs
- β Use mocks to track function calls and simulate behavior
- β
 patch()helps temporarily replace modules, classes, or functions
- β
 Use MagicMockwhen mocking magic methods (__len__,__getitem__, etc.)
βοΈ Real-World Relevance:
Used in unit testing, CI/CD pipelines, test-driven development, and mock API testing.
β FAQ β Python Mocking & Stubbing
β What is the difference between Mock and MagicMock?
β
 MagicMock includes default implementations for all magic methods like __str__, __len__, __getitem__, etc.
β Should I mock everything in a test?
β No. Only mock external dependenciesβkeep tests readable and relevant.
β Can I simulate exceptions with mocks?
β
 Yes, using side_effect:
mock.side_effect = ValueError("Boom!")
β How do I test if a function was called?
β Use:
mock.assert_called()
mock.assert_called_with(args)
β Does mocking slow down tests?
β Noβit makes tests faster by removing external I/O.
Share Now :
