How to Mock a GraphQL Backend in Python
Create an in-memory GraphQL mock backend using dataclasses and resolver methods returning plain dictionaries.
Python code
46 linesfrom dataclasses import dataclass, asdict
from typing import Any, Dict, List
@dataclass
class Product:
id: int
name: str
price: float
@dataclass
class User:
id: int
username: str
class MockGraphQLBackend:
def __init__(self) -> None:
self.products = [
Product(id=1, name="Laptop", price=1200.0),
Product(id=2, name="Mouse", price=25.0),
]
self.users = [
User(id=1, username="alice"),
User(id=2, username="bob"),
]
def resolve_product(self, product_id: int) -> Dict[str, Any] | None:
product = next((p for p in self.products if p.id == product_id), None)
return asdict(product) if product else None
def resolve_all_products(self) -> List[Dict[str, Any]]:
return [asdict(p) for p in self.products]
def resolve_user(self, user_id: int) -> Dict[str, Any] | None:
user = next((u for u in self.users if u.id == user_id), None)
return asdict(user) if user else None
if __name__ == "__main__":
backend = MockGraphQLBackend()
print("All products:", backend.resolve_all_products())
print("Product 1:", backend.resolve_product(1))
print("User 2:", backend.resolve_user(2))
print("Missing product:", backend.resolve_product(999))
Output
All products: [{'id': 1, 'name': 'Laptop', 'price': 1200.0}, {'id': 2, 'name': 'Mouse', 'price': 25.0}]
Product 1: {'id': 1, 'name': 'Laptop', 'price': 1200.0}
User 2: {'id': 2, 'username': 'bob'}
Missing product: None
How it works
The @dataclass decorator automatically generates __init__ and __repr__ methods for the Product and User classes. The asdict helper converts a dataclass instance into a plain dictionary, matching what a typical GraphQL resolver returns. Each resolve_* method mimics a GraphQL field resolver, using next with a generator to find a matching item or return None if not found. This pattern keeps mock data isolated from real services and allows easy swapping with real resolvers later.
Common mistakes
- Forgetting to convert dataclass instances to dictionaries before returning them, leading to serialization errors.
- Using a list comprehension instead of `next(...)` for lookup, which scans the entire list even after a match is found.
- Hardcoding data inside the class instead of making it configurable, reducing reusability.
Variations
- Use a dictionary keyed by id for O(1) lookups instead of a list.
- Make the data dynamic by accepting initial data in the constructor.
Real-world use cases
- Standing up a local mock GraphQL endpoint in development to let frontend teams work without the real backend.
- Using a mock resolver in unit tests to simulate server responses without network calls.
- Prototyping a BFF (backend-for-frontend) service by quickly validating data shapes and queries before wiring real APIs.
Sponsored
More from Microservices patterns
- BFF aggregation pattern: combine multiple service responses in Python easy
- Backward Compatible Schema Evolution in Python medium
- Bulkhead Thread Pool per Service Mock in Python medium
- CQRS with Separate Read and Write Repositories in Python medium
- Cache-Aside Pattern in Python: Per-Service Mock easy
- Consumer Driven Contract Pact Mock in Python medium
Keep learning
Related tutorials and quizzes for this topic.