How to Write a Contract Test with Mock in Python

Use unittest.mock to verify a consumer's expectations match the provider's response shape in a Python contract test.

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

Python code

30 lines
Python 3.9+
from unittest.mock import Mock

# Contract test: verify consumer expects data shape that provider delivers.
# We mock the provider and assert the consumer's calls match the agreed contract.

def fetch_user(provider_client, user_id):
    """Consumer code: expects provider to return {'id', 'name', 'email'}."""
    response = provider_client.get_user(user_id)
    if not response or not all(k in response for k in ('id', 'name', 'email')):
        raise ValueError(f"Provider contract violated for user {user_id}")
    return response

def test_consumer_contract():
    # Mock the provider with a valid contract-shaped response
    mock_provider = Mock()
    mock_provider.get_user.return_value = {
        'id': 42,
        'name': 'Alice',
        'email': 'alice@example.com'
    }

    result = fetch_user(mock_provider, 42)

    # Verify the consumer made exactly the expected call (contract on request)
    mock_provider.get_user.assert_called_once_with(42)
    assert result == {'id': 42, 'name': 'Alice', 'email': 'alice@example.com'}
    print("Consumer contract test passed: provider response matches expectation.")

if __name__ == "__main__":
    test_consumer_contract()

Output

stdout
Consumer contract test passed: provider response matches expectation.

How it works

The Mock class from unittest.mock simulates the provider, allowing you to test the consumer in isolation. By setting return_value on the mock, you define the contract shape the provider must deliver. The consumer code validates this shape and raises if fields are missing, ensuring contract compliance. assert_called_once_with verifies the consumer made the exact expected call, checking the request side of the contract. This pattern catches mismatches early without needing a live provider.

Common mistakes

  • Forgetting to assert the mock was called with the correct arguments
  • Not validating the response shape in the consumer code when testing the contract
  • Using a real provider instead of a mock, making the test slow and flaky

Variations

  1. Use pytest with a fixture to create the mock provider and keep tests DRY
  2. Add a schema validation library like pydantic in the consumer to enforce the contract

Real-world use cases

  • Verifying that a frontend service expects the same user fields an API returns before deployment.
  • Testing a payment gateway client against a mocked provider to prevent integration failures in CI.
  • Validating an internal microservice's API contract when the provider team changes response formats.

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.