Quick Start Guide
Getting started with Mongomock is straightforward. This guide covers how to set up and verify tests using direct database client injection or global runtime patching.
Method 1: Direct Client Injection
If your codebase accepts a database client or collection instance as an argument, you can pass a mongomock.MongoClient directly into your application components.
1. Write the Application Logic
Create a service class that manages user profile records:
# services.py
class ProfileService:
def __init__(self, db_collection):
self.collection = db_collection
def update_user_email(self, user_id, new_email):
if not new_email or "@" not in new_email:
raise ValueError("Invalid email address format")
result = self.collection.update_one(
{"_id": user_id},
{"$set": {"email": new_email, "updated_at": "modified"}},
upsert=True
)
return result.modified_count == 1 or result.upserted_id is not None
2. Write the Unit Test
Test the service class in-memory with pytest using mongomock.MongoClient:
# test_services.py
import pytest
import mongomock
from services import ProfileService
def test_update_user_email_upsert():
# Instantiate an in-memory client and collection
client = mongomock.MongoClient()
mock_collection = client.user_database.profiles
service = ProfileService(mock_collection)
# Execute the service call
success = service.update_user_email("user_100", "user@example.com")
# Assert return status
assert success is True
# Retrieve and verify document state from mock store
document = mock_collection.find_one({"_id": "user_100"})
assert document is not None
assert document["email"] == "user@example.com"
assert document["updated_at"] == "modified"
Method 2: Global PyMongo Patching
If your code handles client connections internally (such as instantiating pymongo.MongoClient inside function bodies), you can intercept those connections globally using the @mongomock.patch decorator.
1. Write the Application Code
# app.py
import pymongo
def register_login_event(host, username):
# Connects internally to a target server
client = pymongo.MongoClient(host)
event = {
"username": username,
"login_time": "now" # simplistic representation
}
client.analytics.login_logs.insert_one(event)
2. Write the Mock Test
Intercept the connection by specifying the target server address inside the patch decorator:
# test_app.py
import pymongo
import mongomock
from app import register_login_event
# Configure the decorator to intercept connections targeting database.internal
@mongomock.patch(servers=(('database.internal', 27017),))
def test_register_login_event():
register_login_event("mongodb://database.internal:27017", "alice")
# Establish a separate connection to verify the data in-memory
verification_client = pymongo.MongoClient("mongodb://database.internal:27017")
stored_log = verification_client.analytics.login_logs.find_one({"username": "alice"})
assert stored_log is not None
assert stored_log["login_time"] == "now"
Core Best Practices for Testing
- Avoid Shared Client Pollution: Create a fresh
mongomock.MongoClientinstance for each test case. This keeps tests isolated and prevents data from leaking between runs. - Test Isolation with Decorators: When using
@mongomock.patch, make sure it wraps test methods cleanly. This ensures that global mock states are cleared between test executions. - Use PyMongo Exceptions: If your production code catches database errors, run Mongomock with PyMongo installed (
pip install mongomock[pymongo]). This ensures Mongomock throws real PyMongo exceptions likeDuplicateKeyErrororOperationFailureinstead of its custom fallback classes.
Now that you have seen the basic setups, you can dive deeper into how Mongomock's memory, threads, and clocks work in the Core Concepts Guide.