Skip to main content

SpecRec ObjectFactory dependency injection for Python

Project description

SpecRec for Python

Make legacy Python code testable with minimal changes

Installation

pip install specrec-python

ObjectFactory: Breaking Hard Dependencies

Turn untestable legacy code into testable code by replacing direct instantiation with factory calls.

The Problem

Legacy code with hard dependencies:

class UserService:
    def process_user(self, user_id):
        # Hard to test - always hits real database
        repo = SqlRepository("server=prod;database=users")
        user = repo.get_user(user_id)
        return user

The Solution

Replace new with create():

from specrec import create

class UserService:
    def process_user(self, user_id):
        # Now testable - can inject test doubles
        repo = create(SqlRepository)("server=prod;database=users")
        user = repo.get_user(user_id)
        return user

Writing Tests

Basic Test Setup

from specrec import create, set_one, context

def test_user_service():
    # Create test double
    mock_repo = MockSqlRepository()
    mock_repo.users = {"123": User("John", "john@example.com")}

    with context():
        # Next create() call returns our mock
        set_one(SqlRepository, mock_repo)

        # Test the code
        service = UserService()
        user = service.process_user("123")

        assert user.name == "John"

Persistent Test Doubles

from specrec import set_always, clear_one

def test_multiple_calls():
    mock_repo = MockSqlRepository()

    with context():
        # All create() calls return our mock
        set_always(SqlRepository, mock_repo)

        service = UserService()
        user1 = service.process_user("123")  # Uses mock
        user2 = service.process_user("456")  # Uses mock too

API Reference

Core Functions

  • create(cls) - Returns a factory function for the class
  • create_direct(cls, *args, **kwargs) - Create instance directly
  • set_one(cls, instance) - Return test double once, then normal instances
  • set_always(cls, instance) - Always return test double
  • clear_one(cls) - Clear test doubles for specific type
  • clear_all() - Clear all test doubles
  • context() - Context manager for automatic cleanup

Advanced Usage

Custom Factory Instance

from specrec import ObjectFactory

# Create dedicated factory
api_factory = ObjectFactory()
create_api_service = api_factory.create(ApiService)
service = create_api_service("https://api.example.com")

Constructor Parameter Tracking

from specrec.interfaces import IConstructorCalledWith, ConstructorParameterInfo
from typing import List

class TrackedService(IConstructorCalledWith):
    def __init__(self, host: str, port: int):
        self.host = host
        self.port = port
        self.constructor_params: List[ConstructorParameterInfo] = []

    def constructor_called_with(self, params: List[ConstructorParameterInfo]) -> None:
        self.constructor_params = params

# Usage
service = create(TrackedService)("localhost", 8080)
print(service.constructor_params[0].name)   # "host"
print(service.constructor_params[0].value)  # "localhost"

Object Registration

from specrec import register_object, get_registered_object

config = DatabaseConfig()
object_id = register_object(config, "db-config")

# Later retrieve it
retrieved = get_registered_object("db-config")

Requirements

  • Python 3.8+
  • typing-extensions (for Python < 3.10)

License

PolyForm Noncommercial License 1.0.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

specrec_python-0.1.1.tar.gz (16.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

specrec_python-0.1.1-py3-none-any.whl (10.9 kB view details)

Uploaded Python 3

File details

Details for the file specrec_python-0.1.1.tar.gz.

File metadata

  • Download URL: specrec_python-0.1.1.tar.gz
  • Upload date:
  • Size: 16.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.12

File hashes

Hashes for specrec_python-0.1.1.tar.gz
Algorithm Hash digest
SHA256 8f59c21d00928784fdfbd4bd9b5d91eecb25f9c47c2ba969e69c416a9b8548f3
MD5 ec92d10d87c2e04a1cd5adddd0572903
BLAKE2b-256 f0fd3bd974c62cccf157535c2fba0fb66fe4ce39aaddf6fdcc10da31698ae820

See more details on using hashes here.

File details

Details for the file specrec_python-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: specrec_python-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 10.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.12

File hashes

Hashes for specrec_python-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 90a4ade23c83ca9eca4981a93cab084b72963bfac03bd24ee25bd02bd6dd7352
MD5 4b4041e3d4412afa2b959fa9c8f297b7
BLAKE2b-256 5e9b58a6c7e4defdbeaa5599db0e9c700bc64a6ceb4414b8a0e16aabdd0658b6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page