How to Mock return_value with MagicMock in Python unittest

Use unittest.mock.MagicMock to replace a dependency and set return_value to control what a mocked method returns during unit tests.

Easy Python 3.9+ Aug 9, 2026 Testing & modern typing 12 views 0 copies

Python code

31 lines
Python 3.9+
import unittest
from unittest.mock import MagicMock


class PaymentGateway:
    def charge(self, amount):
        raise NotImplementedError


class OrderService:
    def __init__(self, gateway):
        self.gateway = gateway

    def process_order(self, amount):
        return self.gateway.charge(amount)


class TestOrderService(unittest.TestCase):
    def test_process_order_returns_charge_result(self):
        gateway = MagicMock()
        gateway.charge.return_value = {"status": "success"}
        service = OrderService(gateway)

        result = service.process_order(100)

        self.assertEqual(result, {"status": "success"})
        gateway.charge.assert_called_once_with(100)


if __name__ == "__main__":
    unittest.main()

Output

stdout
Ran 1 test in 0.002s

OK

How it works

MagicMock automatically creates mock methods and attributes when accessed, so gateway.charge is a mock object you can configure. Setting return_value tells that mock what to return when called, which lets you test OrderService in isolation without a real PaymentGateway. The assert_called_once_with(100) verifies the gateway was called exactly once with the correct argument. Because MagicMock mimics any object, it fits cleanly into dependency injection patterns.

Common mistakes

  • Using `return_value` on the mock itself instead of on the specific method mock, e.g. `gateway.return_value` instead of `gateway.charge.return_value`.
  • Forgetting to call `assert_called_once_with` or using it on the wrong mock method.
  • Creating a new MagicMock inside the test but not injecting it into the service, so the mock never gets used.

Variations

  1. Use `spec=PaymentGateway` to restrict mock attributes to those on the real class.
  2. Use `side_effect` to return different values on consecutive calls or raise exceptions.

Real-world use cases

  • Testing an order service without hitting a real payment provider, returning a fixed success payload per test.
  • Simulating error responses from an external API to verify your code handles failures gracefully.
  • Mocking database session objects in repository tests to avoid live database dependencies.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Testing & modern typing

Related tutorials and quizzes for this topic.