Testing Strategies & Mock Adapters
Relevant source files
The following files were used as context for generating this wiki page:
Forze utilizes a multi-tiered testing strategy designed to ensure reliability across domain logic, application contracts, and infrastructure integrations. A central component of this strategy is the forze_mock package, which provides high-fidelity, in-memory implementations of core infrastructure ports. These mock adapters allow developers to verify application behavior, complex queries, and transactional flows without the overhead or non-determinism of external databases.
Sources: tests/README.md:3-11, src/forze_mock/adapters/document.py
Testing Tiers
The project categorizes tests into four distinct tiers, ranging from pure logic verification to full cross-package integration.
| Tier | Location | Purpose |
|---|---|---|
| L0 | tests/unit/ | Pure modules: Renderers, scrubbing, cursors, error mapping. |
| L1 | tests/unit/ + forze_mock | Lifecycle hooks, ExecutionContext, and routed client wiring. |
| L2 | tests/integration/ | Single backend smoke tests and adapter path verification. |
| L3 | tests/integration/ | Cross-package integration (e.g., Postgres + Redis snapshots). |
| Perf | tests/perf/ | Throughput and latency benchmarks. |
Sources: tests/README.md:13-21
Execution Workflow
Tests are executed using the just command runner. The default suite (just test) includes unit and integration tests but excludes performance benchmarks.
The performance gate in CI fails if a regression exceeds 15% of the median of per-run minimums on the same runner.
Sources: tests/README.md:23-33, CONTRIBUTING.md:295-305
Mock Adapters Architecture
Mock adapters in Forze are not mere stubs; they implement the full logic of the protocols they represent, including query DSL evaluation, optimistic concurrency (revision checks), and soft-deletion.
MockState and Namespacing
All mock adapters share a MockState object, which serves as the in-memory data store. Data is isolated within namespaces, allowing multiple adapters (e.g., a Document adapter and a Search adapter) to operate on the same underlying data set.
Key Mock Components
MockDocumentAdapter
Implements DocumentQueryPort and DocumentCommandPort. It supports:
- CRUD Operations: Creating, updating, and killing documents.
- Query DSL: Filtering via
$values,$and,$or, and field comparisons via$fields. - Optimistic Concurrency: Verifies
rev(revision) numbers during updates to detect conflicts. - Soft Deletion: Integrates with
SoftDeletionMixinto manageis_deletedflags.
Sources: src/forze_mock/adapters/document.py, tests/unit/test_forze/application/contracts/test_document_ports.py:168-185, tests/unit/test_forze_mock/test_mock_adapters.py:175-185
MockSearchAdapter
Provides in-memory full-text search capabilities by scanning the shared MockState. It supports query term matching, phrase combination (all/any), and limit/offset pagination.
Sources: tests/unit/test_forze/application/test_stub_search.py:68-85
MockCounterAdapter
Simulates atomic counters (e.g., for human-readable IDs). It is async-safe and supports both single increments (incr) and batch increments (incr_batch).
Sources: tests/unit/test_forze_mock/test_mock_adapters.py:220-227
Data Flow: In-Memory Mutation
When a mutation occurs via a Mock Command Port, the adapter performs several steps to mirror real database behavior, including codec transformation and state persistence.
Mock adapters explicitly use DocumentCodecs from the DocumentSpec to ensure that transformation logic (including encryption/decryption simulation) is exercised during unit tests.
Sources: tests/unit/test_forze_mock/test_mock_adapters.py:192-218
Query and Filtering Logic
Mock adapters implement a robust subset of the Forze Query DSL. This allows testing of complex data retrieval logic without a real database.
| Operator | Mock Implementation Detail |
|---|---|
$values | Matches field values directly or via nested operators like $in or $gte. |
$fields | Compares two fields within the same document. |
$groups | Used in select_page_aggregated to perform in-memory grouping. |
$computed | Supports aggregation functions like $sum, $count, and $median. |
Sources: tests/unit/test_forze_mock/test_mock_adapters.py:118-135, tests/unit/test_forze_mock/test_mock_adapters.py:148-173
Aggregation Example
The Mock adapter can calculate complex metrics in-memory, such as revenue or median price per category, facilitating the testing of analytical handlers.
Sources: tests/unit/test_forze_mock/test_mock_adapters.py:155-165
Conclusion
The combination of a tiered testing strategy and high-fidelity mock adapters allows Forze applications to maintain high confidence in code quality. By mirroring the behavior of production adapters (Postgres, Mongo, etc.), forze_mock ensures that unit tests are not just superficial checks but deep validations of business logic and infrastructure contracts.