doido_model/factory.rs
1//! Test factories (FactoryBot-style): build test records with unique sequences.
2//!
3//! A type implements [`Factory::build`] to produce a default instance — usually
4//! using [`sequence`] for unique fields — and gets [`Factory::build_list`] for
5//! free. Pair with [`crate::testing::TestDb`] to persist them.
6
7use std::sync::atomic::{AtomicU64, Ordering};
8
9static SEQUENCE: AtomicU64 = AtomicU64::new(1);
10
11/// A process-global, monotonically increasing counter for unique test values
12/// (FactoryBot `sequence`), e.g. `format!("user{}@example.com", sequence())`.
13pub fn sequence() -> u64 {
14 SEQUENCE.fetch_add(1, Ordering::Relaxed)
15}
16
17/// Builds test instances of a type.
18pub trait Factory: Sized {
19 /// Build one instance (typically using [`sequence`] for unique fields).
20 fn build() -> Self;
21
22 /// Build `n` instances.
23 fn build_list(n: usize) -> Vec<Self> {
24 (0..n).map(|_| Self::build()).collect()
25 }
26}