Skip to main content

Module factory

Module factory 

Source
Expand description

Test fixtures — Factory and HasFactory.

ⓘ
#[derive(Entity, Default, Clone, Factory)]
struct User { id: u64, email: String, verified_at: Option<DateTime<Utc>> }

let users = User::factory()
    .count(3)
    .sequence(|user, i| user.email = format!("user{i}@example.com"))
    .state(|user| user.verified_at = Some(Utc::now()))
    .create(&*users)
    .await?;

TestApp solved booting an application. This is the other half: getting rows into it without every test constructing them field by field, which is why a suite’s setup ends up longer than its assertions.

§What a factory is for, and what it is not

It builds a row that is valid and uninteresting. Every field a test does not care about gets a value that will not trip a constraint, and the one or two fields the test is about are set with state.

That is the whole point: a test that spells out fifteen fields to assert on one of them has buried its subject. A reader cannot tell which value matters, and neither can the next person to change the schema.

§Unique columns need a sequence

A derived factory builds from Default, and three defaults are three identical rows — which a UNIQUE index refuses on the second. Anything unique needs sequence, which is handed the index:

ⓘ
.sequence(|user, i| user.email = format!("user{i}@example.com"))

Deliberately not automatic. A factory that invented unique values would have to guess which columns are unique and what shape they take, and a guess that is wrong produces a row that fails to insert for a reason nobody can see from the test.

Structs§

Factory
Builds models for a test.

Traits§

HasFactory
A model with a factory.