Configuration¶
All configuration is done through SomeConfigBuilder. Every option has sensible defaults so you can start using some() immediately without any setup.
The SomeConfigBuilder class¶
Configuration lambdas (someSetup {}, some {}) receive a SomeConfigBuilder receiver with mutable properties. Calling build() produces an immutable SomeConfig.
class SomeConfigBuilder {
var nullableStrategy: NullableStrategy = NullableStrategy.NullOnCircularReference
var stringStrategy: StringStrategy = StringStrategy.Random()
var collectionStrategy: CollectionStrategy = CollectionStrategy()
var seed: Long? = null
fun <T : Any> register(kClass: KClass<T>, factory: FixtureContext.() -> T)
fun build(): SomeConfig
}
The resulting SomeConfig is immutable:
data class SomeConfig(
val nullableStrategy: NullableStrategy = NullableStrategy.NullOnCircularReference,
val stringStrategy: StringStrategy = StringStrategy.Random(),
val collectionStrategy: CollectionStrategy = CollectionStrategy(),
val seed: Long? = null,
val factories: Map<KClass<*>, FixtureContext.() -> Any?> = emptyMap(),
)
Creating configuration objects¶
Global configuration with someSetup¶
Use someSetup {} to create a reusable Some instance with a shared configuration:
val some = someSetup {
seed = 12345L
stringStrategy = StringStrategy.Uuid
collectionStrategy = CollectionStrategy(3..7)
}
val user = some<User>()
val order = some<Order>()
Inline configuration with some {}¶
Pass a configuration lambda directly to some() for one-off overrides:
val user = some<User> {
nullableStrategy = NullableStrategy.AlwaysNull
stringStrategy = StringStrategy.Readable
}
The inline form creates a new builder from the default configuration, applies your overrides, and generates a single instance — without affecting the global defaults.
Aggregated configuration¶
You can override configuration on a per-call basis without mutating the base instance:
val baseSome = someSetup {
seed = 42L
nullableStrategy = NullableStrategy.NeverNull
}
// Override for a single call — base config is NOT mutated
val result: Person = baseSome {
nullableStrategy = NullableStrategy.AlwaysNull
}
// baseSome still uses NeverNull
val stillNeverNull: Person = baseSome()
Default configuration¶
| Property | Default | Description | Docs |
|---|---|---|---|
nullableStrategy |
NullableStrategy.NullOnCircularReference |
null for nullable circular references |
NullableStrategy |
stringStrategy |
StringStrategy.Random() |
Random lowercase alphabetic, 8 characters | StringStrategy |
collectionStrategy |
CollectionStrategy() |
Collections of 1 to 5 elements | CollectionStrategy |
seed |
null |
Uses non-deterministic Random.Default |
— |
Seed¶
Setting seed produces deterministic output — the same seed always generates the same values:
val some1 = someSetup { seed = 12345L }
val some2 = someSetup { seed = 12345L }
some1<User>() == some2<User>() // true
Without a seed, Random.Default is used, meaning each generation produces different random values.
Internally, SomeConfig.buildRandom() creates a seeded kotlin.random.Random if seed is set, or falls back to Random.Default.
Custom factories¶
SomeConfigBuilder provides a register function to add custom factory functions for specific types:
val some = someSetup {
register(Email::class) { Email("${some<String>()}@example.com") }
register(CustomerId::class) { CustomerId(some<UUID>().toString()) }
}
See Custom Factories for detailed documentation.