Test Fixtures & Mocking
Relevant source files
The following files were used as context for generating this wiki page:
Introduction
Test Fixtures and Mocking within the flext-web project provide a structured, reusable approach to isolating components during validation. By leveraging the Pytest framework, the project ensures that units of code can be tested independently of external dependencies, such as LDAP servers, databases, or third-party APIs. This isolation is critical for maintaining high coverage standards, specifically 85%+ for foundation libraries and 75%+ for application-level domain libraries.
The system relies on a hierarchical test structure where fixtures are centrally managed in tests/fixtures/ and shared via conftest.py. This setup supports various test categories, including isolated unit tests, component-interaction integration tests, and full workflow end-to-end (e2e) scenarios. For more information on the broader development standards, refer to the Development Guide.
Sources: guides/testing.md:1-40, tests/README.md:1-20
Test Fixture Architecture
The project utilizes Pytest fixtures to manage the lifecycle of test data and service instances. Fixtures are defined with specific scopes (e.g., function, class, or module) to optimize performance while ensuring test independence.
Data Flow for Fixture Injection
The following diagram illustrates how fixtures are defined and injected into test classes to provide consistent service states.
The diagram shows the distribution of fixtures from configuration files to specific test types.
Sources: guides/testing.md:150-180, tests/README.md:5-15
Core Fixture Types
| Fixture Category | Purpose | Example Usage |
|---|---|---|
| Service Fixtures | Provides instantiated service objects with pre-defined settings. | ldif_service for parsing tests. |
| Config Fixtures | Supplies Typed Settings objects (Pydantic models). | FlextLdifSettings with custom batch sizes. |
| Content Fixtures | Provides raw string or JSON data for parsing and migration. | sample_ldif_content strings. |
| Directory Fixtures | Manages temporary file paths for filesystem-dependent tests. | temp_directories using tmp_path. |
Sources: guides/testing.md:152-195
Mocking Strategies
FLEXT employs two primary strategies for dependency isolation: Isolation Mocking for unit tests and Container Stubbing for integration tests.
Unit Test Mocking
Unit tests utilize the unittest.mock library to patch external modules. This ensures that the test remains fast and does not require an active network or filesystem.
from unittest.mock import Mock, patch
def test_with_mocked_dependency():
"""Test with mocked external dependency."""
with patch("flext_ldif.external_service") as mock_service:
# Configure mock
mock_service.process.return_value = r.ok("processed")
# Test function that uses mock
result = my_function()
# Verify mock was called
mock_service.process.assert_called_once()
assert result.success
Sources: guides/testing.md:210-230
Integration Test Stubbing (DI Container)
Integration tests interact with the FlextContainer for Dependency Injection. Instead of patching at the module level, a Mock object is bound to the container registry, allowing the system's internal logic to resolve the stub naturally.
This sequence demonstrates the service resolution flow using a stubbed container.
Sources: guides/testing.md:235-255, guides/development.md:140-160
Implementation of Fixture Classes
In flext-web, complex fixtures are often encapsulated in specialized classes to manage setup and teardown logic, such as the WebAuthFixture used for authentication testing.
Example: Authentication Fixture Usage
The WebAuthFixture provides canonical credentials and rejected states to verify authentication logic through the web facade.
class TestsFlextWebService:
def test_authenticate_success(self) -> None:
"""Authentication succeeds for the canonical test credentials."""
credentials = WebAuthFixture().credentials
result = web.authenticate(credentials)
tm.ok(result)
tm.that(result.value.user_id, eq=credentials.username)
Sources: tests/unit/test_services.py:27-33, tests/fixtures/auth.py
Test Data Management
Test data is segregated into a dedicated fixtures directory within the tests folder. This directory contains static files (LDIF, JSON, YAML) used to simulate real-world payloads.
Loading Mechanisms
The project provides helper functions to load these static assets into memory:
load_test_fixture: Reads a file as a string.load_json_fixture: Parses a file into aJsonMapping.
Sources: guides/testing.md:295-320
Best Practices for Fixtures
The following principles are enforced to maintain test quality:
- Test Independence: Every test should use a fresh instance of a fixture or service to prevent side effects between tests.
- Descriptive Naming: Fixtures and tests must clearly state their purpose (e.g.,
test_parse_valid_ldif_returns_success). - Specific Assertions: Tests must use granular assertions on specific fields rather than general truthiness checks.
- Zero-Debt Baseline: All tests must pass with zero violations of the project's quality gates.
Sources: guides/testing.md:365-410, index.md:25-35
Conclusion
Test fixtures and mocking are foundational to the flext-web quality assurance strategy. By combining Pytest's flexible fixture system with Flext's Dependency Injection container, the project achieves a robust testing environment that supports rapid development while maintaining high enterprise-grade reliability. These patterns ensure that any change can be validated against a "Zero-Debt" baseline using standard make test and make val workflows.
Sources: guides/development.md:180-200, index.md:30-40