Background
PR #175 introduced a Clock trait (SystemClock / FixedClock) into src/tools/builder/core/wrapper.rs to enable one deterministic timing assertion in wrapper_tests.rs. The trait adds measurable production complexity — an Arc<dyn Clock> field, a trait definition, a SystemClock impl, and a test-only constructor — without a stated reuse strategy or an explanation of when this pattern should be preferred over alternatives.
Separately, issue #113 tracks replacing hand-rolled stubs with mockall-generated mocks. These two pieces of work share the same root concern: the project lacks a single, authoritative source of truth for how time-dependent and other injectable dependencies should be tested deterministically.
Required work
-
Testing-strategy documentation — Update docs/testing-strategy.md (and/or docs/reliable-testing-in-rust-via-dependency-injection.md / docs/testing-abstractions.md) to include a dedicated section on deterministic timing tests. The section must:
- State the rule: wall-clock calls (
Instant::now, Utc::now, SystemTime::now) must never appear in test assertions.
- Document the approved pattern: define a
Clock trait (or equivalent) with a production SystemClock impl and an injectable FixedClock test double.
- Set out where shared clock/time abstractions should live (e.g. a
crate::clock module) to avoid re-implementing the same trait per feature module.
- Cover repeatability requirements: test doubles must be
Clone, Send, and Sync; snapshot assertions over time-containing output must use the injected fixed value.
-
Mock injection guidance — Add or extend documentation to cover:
- When to use
mockall-generated mocks vs hand-written fakes vs FixedClock-style test doubles.
- The approved
mockall / mockable usage patterns for async traits, including the #[automock] and #[cfg_attr(test, automock)] forms.
- A worked example (ideally a doctest or inline code block in the guide) showing a
Clock-injected struct under test.
-
Shared clock module — Evaluate extracting the Clock trait and SystemClock / FixedClock impls into a shared location (e.g. src/clock.rs or src/testing/clock.rs) so the pattern is reusable across crates without per-module duplication.
Acceptance criteria
docs/testing-strategy.md (or a linked testing-abstractions document) contains the deterministic-timing rule and the approved pattern with a code example.
- The mock-injection section documents
mockall usage and the criteria for choosing between mockall and hand-written doubles.
- A shared clock module exists (or a documented rationale for not extracting one is present in the ADR log).
cargo nextest run --workspace --features test-helpers --profile default passes.
References
Background
PR #175 introduced a
Clocktrait (SystemClock/FixedClock) intosrc/tools/builder/core/wrapper.rsto enable one deterministic timing assertion inwrapper_tests.rs. The trait adds measurable production complexity — anArc<dyn Clock>field, a trait definition, aSystemClockimpl, and a test-only constructor — without a stated reuse strategy or an explanation of when this pattern should be preferred over alternatives.Separately, issue #113 tracks replacing hand-rolled stubs with
mockall-generated mocks. These two pieces of work share the same root concern: the project lacks a single, authoritative source of truth for how time-dependent and other injectable dependencies should be tested deterministically.Required work
Testing-strategy documentation — Update
docs/testing-strategy.md(and/ordocs/reliable-testing-in-rust-via-dependency-injection.md/docs/testing-abstractions.md) to include a dedicated section on deterministic timing tests. The section must:Instant::now,Utc::now,SystemTime::now) must never appear in test assertions.Clocktrait (or equivalent) with a productionSystemClockimpl and an injectableFixedClocktest double.crate::clockmodule) to avoid re-implementing the same trait per feature module.Clone,Send, andSync; snapshot assertions over time-containing output must use the injected fixed value.Mock injection guidance — Add or extend documentation to cover:
mockall-generated mocks vs hand-written fakes vsFixedClock-style test doubles.mockall/mockableusage patterns for async traits, including the#[automock]and#[cfg_attr(test, automock)]forms.Clock-injected struct under test.Shared clock module — Evaluate extracting the
Clocktrait andSystemClock/FixedClockimpls into a shared location (e.g.src/clock.rsorsrc/testing/clock.rs) so the pattern is reusable across crates without per-module duplication.Acceptance criteria
docs/testing-strategy.md(or a linked testing-abstractions document) contains the deterministic-timing rule and the approved pattern with a code example.mockallusage and the criteria for choosing between mockall and hand-written doubles.cargo nextest run --workspace --features test-helpers --profile defaultpasses.References