Skip to main content

Fixtures

Kensa Fixtures are collections of type-safe, lazily-created test data values. Each test invocation has its own discreet set of Fixtures. They are shared across given, whenever, and then steps via the context objects.

Full example

The code on this page is taken from clearwave-example — a complete working project that demonstrates fixtures, captured outputs, sequence diagrams, and async assertions.


Defining Fixtures

Fixtures must be defined inside a FixtureContainer object. This can be an instance of a Java class or a Kotlin object. They carry a string key which must be unique — and a factory that creates the value.

Fixtures can depend on up to three other fixtures; the factory for dependent fixtures will receive the resolved parent values at creation time.

It is best to define fixtures as static/public properties, which you can then import by name in your tests.

Primary Fixtures

A primary fixture has no dependencies — its factory takes no arguments.

The key design principle is granularity: define one fixture per meaningful field rather than one fixture per domain object. This lets each field appear by name in the rendered report wherever it is referenced in the test body.

src/test/kotlin/com/clearwave/support/TelecomsFixtures.kt
loading...

Secondary Fixtures

A secondary fixture depends on one or more parent fixtures. Its factory receives the resolved parent values.

2 parents:

src/test/kotlin/com/clearwave/support/TelecomsFixtures.kt
loading...

3 parents — composite object built from individual field fixtures:

src/test/kotlin/com/clearwave/support/TelecomsFixtures.kt
loading...

More than 3 parents — construct a SecondaryFixture directly; its factory lambda receives the full Fixtures map:

src/test/kotlin/com/clearwave/support/TelecomsFixtures.kt
loading...

Using Fixtures in Tests

In given and whenever actions

Access fixtures through the context destructured in each action lambda:

src/test/kotlin/com/clearwave/FeasibilityServiceTest.kt
loading...
src/test/kotlin/com/clearwave/OrderServiceTest.kt
loading...

In the test body — the key rendering pattern

The most important place to use fixture references is directly in the test body, passed as named arguments into assertion helpers. Kensa parses the test source code and when it sees fixtures[voiceDownloadSpeed] (Kotlin) or fixtures(VOICE_DOWNLOAD_SPEED) (Java) in the sentence it substitutes the fixture's display name — Voice Download Speed — rather than the raw value 900. This makes reports self-documenting.

src/test/kotlin/com/clearwave/FeasibilityServiceTest.kt
loading...
src/test/kotlin/com/clearwave/OrderServiceTest.kt
loading...

The assertion helpers simply accept the fixture values as ordinary parameters — they have no special knowledge of Kensa:

src/test/kotlin/com/clearwave/FeasibilityServiceTest.kt
loading...
src/test/kotlin/com/clearwave/OrderServiceTest.kt
loading...

Grouping Fixtures with WithFixturesSuite

When many tests share a large FixtureContainer, importing every fixture individually creates noise. WithFixturesSuite lets you declare one shared interface per container; test classes implement that interface and gain scoped, IDE-assisted block access to all its fixtures.

note

WithFixturesSuite is a Kotlin-only feature. Java tests access fixtures via static imports directly.

Without WithFixturesSuite — each test file imports fixtures individually:

import dev.kensa.fixture.TelecomsFixtures.AccountNumber
import dev.kensa.fixture.TelecomsFixtures.LineProfile
import dev.kensa.fixture.TelecomsFixtures.AppointmentSlot
// ... one import per fixture

class FeasibilityServiceTest : KensaTest(), WithHamkrest {
@Test
fun `can check feasibility`() {
then(theAccountNumber(), equalTo(fixtures[AccountNumber]))
}
}

With WithFixturesSuite — one shared interface, block syntax in tests:

Step 1 — declare the interface once (e.g. in a shared support file):

interface WithTelecomsFixtures : WithFixturesSuite<TelecomsFixtures> {
override val fixturesObject get() = TelecomsFixtures
}

Step 2 — implement it in test classes; access fixtures via a block lambda:

class FeasibilityServiceTest : KensaTest(), WithTelecomsFixtures, WithHamkrest {
@Test
fun `can check feasibility`() {
then(theAccountNumber(), equalTo(fixtures { AccountNumber }))
}

private fun theAccountNumber() = StateCollector { fixtures { AccountNumber } }
}

The block lambda (fixtures { AccountNumber }) is scoped to the FixtureContainer type, so the IDE offers autocomplete over exactly those fixtures — nothing more.

WithFixturesSuite API

MemberDescription
val fixturesObject: FOverride to return the FixtureContainer singleton
fun <T> fixtures(block: F.() -> Fixture<T>): TRetrieves (lazily creates) a fixture via a scoped block

Fixture API Reference

fixture() factory (Kotlin)

// Primary — no dependencies
fun <T> fixture(key: String, highlighted: Boolean = false, factory: () -> T): PrimaryFixture<T>

// Secondary — 1 parent
fun <T, P1> fixture(key: String, parent: Fixture<P1>, highlighted: Boolean = false, factory: (P1) -> T): SecondaryFixture<T>

// Secondary — 2 parents
fun <T, P1, P2> fixture(key: String, parent1: Fixture<P1>, parent2: Fixture<P2>, highlighted: Boolean = false, factory: (P1, P2) -> T): SecondaryFixture<T>

// Secondary — 3 parents
fun <T, P1, P2, P3> fixture(key: String, parent1: Fixture<P1>, parent2: Fixture<P2>, parent3: Fixture<P3>, highlighted: Boolean = false, factory: (P1, P2, P3) -> T): SecondaryFixture<T>

createFixture() factory (Java)

createFixture(String key, Supplier<T> factory)
createFixture(String key, boolean highlighted, Supplier<T> factory)
createFixture(String key, Fixture<P1> parent, Function<P1, T> factory)
createFixture(String key, Fixture<P1> parent1, Fixture<P2> parent2, BiFunction<P1, P2, T> factory)

Fixtures map

Method / operatorDescription
fixtures[fixture]Get (and lazily create) the fixture value
fixtures.values()All fixture values as List<NamedValue>
fixtures.highlightedValues()Only highlighted fixture values

Highlighting

Set highlighted = true on any fixture to have its value appear prominently in the report. This is useful for correlation IDs and other values that should stand out across all interactions.

src/test/kotlin/com/clearwave/support/TelecomsFixtures.kt
loading...

Highlighted values are also accessible separately via fixtures.highlightedValues(), which Kensa uses to render them at the top of the report.