πŸ’‘ Advanced Python Concepts
Estimated reading: 4 minutes 42 views

πŸ§ͺ 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, and patch()
  • How to simulate return values and exceptions
  • Best practices and common pitfalls

βœ… What Are Mocking and Stubbing?

TermDescription
StubA simplified version of a function that returns fixed output
MockA 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

FeatureStubMock
Returns fixed dataβœ… Yesβœ… Yes
Tracks usage❌ Noβœ… Yes (assert_called_with)
Raises exceptionsβœ… Yesβœ… Yes (side_effect)
Best forData setupBehavior verification

πŸ“˜ Best Practices

βœ… Do This❌ Avoid This
Use patch() as a context manager or decoratorForgetting to stop the patch manually
Verify arguments with assert_called_with()Assuming mocks are always called
Use side_effect for exceptions or sequencesHardcoding return values only
Keep mocks focused on one behaviorOver-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 MagicMock when 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 :

Leave a Reply

Your email address will not be published. Required fields are marked *

Share

Python Mocking & Stubbing

Or Copy Link

CONTENTS
Scroll to Top