Pytest Mock Resources
A pytest plugin for easily instantiating reproducible mock resources such as PostgreSQL, MongoDB, Redis, and more. It leverages Docker to manage container lifecycles, providing real service instances for robust integration testing without relying on complex mocks. The library is actively maintained with frequent releases, currently at version 2.12.4.
Warnings
- gotcha Most `pytest-mock-resources` fixtures (PostgreSQL, MongoDB, Redis, MySQL, Redshift) require Docker to be installed and running on the test environment. SQLite is a notable exception.
- gotcha While `pytest-mock-resources` provides 'extras' for installing database drivers (e.g., `[postgres]` for `psycopg2-binary`), the maintainers recommend explicitly installing these client libraries (e.g., `psycopg2-binary`, `pymongo`, `redis`) as first-party dependencies in your project. This avoids potential version conflicts or unexpected behavior.
- gotcha When using asynchronous database fixtures, you will generally need to install `pytest-asyncio` for proper fixture handling and test execution.
- gotcha Running `Redis` tests in parallel (e.g., with `pytest-xdist`) can lead to cross-test state issues if operations like `flushall` are used, as internal Redis database selection mechanisms might not fully isolate tests. The default Redis container limit also restricts simultaneous tests to 16.
- breaking For PostgreSQL drivers, `pytest-mock-resources` versions 2.10.3 and 2.12.3 included fixes for improved default driver selection heuristics and compatibility with `psycopg` (specifically `psycopg2-binary` and async use with the dynamic `psycopg` drivername). If you were relying on older driver auto-detection or using `psycopg` for async, these versions might alter behavior.
- gotcha Running tests with `pytest-mock-resources` in CI/CD environments (e.g., CircleCI, GitLab) often requires specific Docker service configurations and environment variables to ensure the test containers are accessible.
Install
-
pip install pytest-mock-resources pytest -
pip install pytest-mock-resources[postgres] psycopg2-binary
Imports
- create_postgres_fixture
from pytest_mock_resources import create_postgres_fixture
- PostgresConfig
from pytest_mock_resources import PostgresConfig
- create_mongo_fixture
from pytest_mock_resources import create_mongo_fixture
- create_redis_fixture
from pytest_mock_resources import create_redis_fixture
Quickstart
import pytest
from sqlalchemy import create_engine, text
from sqlalchemy.orm import declarative_base, sessionmaker
# Define a simple SQLAlchemy model (if using ORM)
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
def __repr__(self):
return f"<User(id={self.id}, name='{self.name}')>"
from sqlalchemy import Column, Integer, String
from pytest_mock_resources import create_postgres_fixture
# Create a PostgreSQL fixture, providing the SQLAlchemy Base and enabling session
# This fixture will provide a SQLAlchemy session object to tests that request 'pg'
pg = create_postgres_fixture(Base, session=True)
def test_user_creation(pg):
"""Test creating a user in the mock PostgreSQL database."""
# 'pg' is a SQLAlchemy session provided by the fixture
new_user = User(name='Alice')
pg.add(new_user)
pg.commit()
pg.refresh(new_user)
result = pg.execute(text("SELECT name FROM users WHERE id = :id"), {'id': new_user.id}).scalar_one()
assert result == 'Alice'
def test_another_user_creation(pg):
"""Another test, ensuring isolation between tests (new empty database)."""
# This test gets a fresh, empty database instance
assert pg.query(User).count() == 0
new_user = User(name='Bob')
pg.add(new_user)
pg.commit()
assert pg.query(User).count() == 1