Skip to content

Latest commit

 

History

History
86 lines (65 loc) · 3.78 KB

advanced-customisation.adoc

File metadata and controls

86 lines (65 loc) · 3.78 KB

Advanced engine customisation

While the main configuration options should handle the majority of ways to alter how KotlinFixture generates fixtures, perhaps there is core functionality missing, or some other reason where you need finer grained control.

Of course, we would love to hear about it, to help us improve KotlinFixture so please also consider raising issues and creating PRs.

Generators

While factory and property generators have built-in helper functions you can also create your own by adding extension functions to Generator.

Generator provides random for you to use which can be seeded in your fixture definition.

You also have access to fixture for internally generating other classes.

fun Generator<Int>.odd(max: Int = Int.MAX_VALUE): Int  = random.nextInt(max).let {
    it + if (it % 2 == 0) 1 else 0
}

data class Person(val name: String, val age: Int)

fun Generator<Person>.person(child: Boolean): Person = Person(
    name = fixture<String>(),
    age = if (child) random.nextInt(random.nextInt(0, 17)) else random.nextInt(18, 95)
)

Resolvers

The core engine of KotlinFixture is based on a chain of Resolver instances which are queried in sequence. We ask each Resolver if it handles the current input object, and it returns either a generated fixture or Unresolved.Unhandled.

ℹ️
We use Unresolved as nulls are valid fixtures.

The Resolver interface requires the implementation of the resolve function:

fun resolve(context: Context, obj: Any): Any?

Typically, the input object, obj, begins as a KType and as it passes through the resolver chain will be changed to new values, such as a KClass. A recursive call to context.resolve(…) is made with this new value for another Resolver to pick up.

When generating random content, use context.random to retain the ability to provide a seeded random.

Decorators

On the other hand, a Decorator allows you to intercept and modify the Resolver chain and are currently being used for functionality from logging to recursion.

Strategies

To customise the behaviour of a Resolver or Decorator, a strategy can be provided in the configuration, and retrieved using context.strategyOrDefault(…).

For convenience, we add an extension function to the ConfigurationBuilder. For example, see LoggingConfiguration.