💡 Advanced Python Concepts
Estimated reading: 4 minutes 278 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 :
Share

Python Mocking & Stubbing

Or Copy Link

CONTENTS
Scroll to Top