kotlin-faker provides additional functionality outside of data generation from static .yml dictionaries.


Random instance of any class

It is possible to create a random instance of (almost) any class.

There are some rules to keep in mind:

  • By default, the constructor with the least number of arguments is used (This can be configured - read on.)
  • kolin.Array type in the constructor is not supported at the moment

Random instance generation is available through Faker().randomProvider:

class Foo(val a: String)
class Bar(val foo: Foo)

val foo: Foo = faker.randomProvider.randomClassInstance()
val bar: Bar = faker.randomProvider.randomClassInstance()


Pre-Configuring type generation for constructor arguments

Some, or all, of the constructor params can be instantiated with values following some pre-configured logic using typeGenerator or namedParameterGenerator functions. Consider the following example:

class Baz(val id: Int, val uuid: UUID, val relatedUuid: UUID)

val baz: Baz = faker.randomProvider.randomClassInstance {
    typeGenerator<UUID> { UUID.fromString("00000000-0000-0000-0000-000000000000") }
    typeGenerator<Int> { 0 }
    namedParameterGenerator("relatedUuid") { UUID.fromString("11111111-1111-1111-1111-111111111111") }

So for each instance of Baz the following will be true:

baz.id == 0
baz.uuid == UUID.fromString("00000000-0000-0000-0000-000000000000")
baz.relatedUuid == UUID.fromString("11111111-1111-1111-1111-111111111111")

This example itself does not make that much sense, since we're using "static" values, but we could also do something like:

val baz: Baz = faker.randomProvider.randomClassInstance {
    typeGenerator<UUID> { UUID.randomUUID() }

...or even so:

class Person(val id: Int, val name: String)

val person: Person = faker.randomProvider.randomClassInstance {
    typeGenerator<String> { faker.name.fullName() }


Deterministic constructor selection

By default, the constructor with the least number of args is used when creating a random instance of the class. This might not always be desirable and can be configured. Consider the following example:

class Foo
class Bar(val int: Int)
class Baz(val foo: Foo, val string: String)
class FooBarBaz {
    var foo: Foo? = null
        private set
    var bar: Bar? = null
        private set
    var baz: Baz? = null
        private set

    constructor(foo: Foo) {
        this.foo = foo

    constructor(foo: Foo, bar: Bar) : this(foo) {
        this.bar = bar

    constructor(foo: Foo, bar: Bar, baz: Baz) : this(foo, bar) {
        this.baz = baz

If there is a need to use the constructor with 3 arguments when creating an instance of FooBarBaz, we can do it like so:

val fooBarBaz: FooBarBaz = faker.randomProvider.randomClassInstance {
    constructorParamSize = 3
    fallbackStrategy = FallbackStrategy.USE_MAX_NUM_OF_ARGS
assertNotEquals(fooBarBaz.foo, null)
assertNotEquals(fooBarBaz.bar, null)
assertNotEquals(fooBarBaz.baz, null)

In the above example, FooBarBaz will be instantiated with the first discovered constructor that has parameters.size == 3; if there are multiple constructors that satisfy this condition - a random one will be used. Failing that (for example, if there is no such constructor), a constructor with the maximum number of arguments will be used to create an instance of the class.

Alternatively to constructorParamSize, a constructorFilterStrategy config property can be used as well:

val fooBarBaz: FooBarBaz = faker.randomProvider.randomClassInstance {
    constructorFilterStrategy = ConstructorFilterStrategy.MAX_NUM_OF_ARGS
assertNotEquals(fooBarBaz.foo, null)
assertNotEquals(fooBarBaz.bar, null)
assertNotEquals(fooBarBaz.baz, null)

The above has the following rules:

  • constructorParamSize config property takes precedence over constructorFilterStrategy
  • both can be specified at the same time, though in most cases it probably makes more sense to use fallbackStrategy with constructorParamSize as it just makes things a bit more readable
  • configuration properties that are set in randomClassInstance block will be applied to all "children" classes. For example classes Foo, Bar, and Baz will use the same random instance configuration settings when instances of those classes are created in FooBarBaz class.


Configuring the size of generated Collections

Support for kotlin.collections.Collection parameter types - List, Set and Map has been added in version 1.9.0 and with that - a new configuration parameter to configure the size of the generated collection.

By default, all collections will be generated with only 1 element:

class Foo(
    val list: List<String>,
    val set: Set<String>,
    val map: Map<String, Int>

val foo = faker.randomProvider.randomClassInstance<Foo>()

assertEquals(foo.list.size, 1)
assertEquals(foo.set.size, 1)
assertEquals(foo.map.size, 1)

This can be configured using collectionsSize parameter:

class Foo(
    val list: List<String>,
    val set: Set<String>,
    val map: Map<String, Int>

val foo = faker.randomProvider.randomClassInstance<Foo> {
    collectionsSize = 6

assertEquals(foo.list.size, 6)
assertEquals(foo.set.size, 6)
assertEquals(foo.map.size, 6)


Note that the collectionsSize configuration parameter affects all 3 types of Collections.


It is also worth noting that typeGenerator<Foo> { ... } configuration, which was covered above, will not affect Foo typed elements in a generated collection.

Consider the following example. If typeGenerator<String> { "a string" } would affect String typed elements of Set, the resulting generated set would be of size 1:

class TestClass(
    val string: String,
    val set: Set<String>

val testClass = faker.randomProvider.randomClassInstance<TestClass> {
    typeGenerator { "a string" }
    collectionsSize = 10

assertEquals(testClass.string, "a string")
assertEquals(testClass.set.size, 10)

At the same time, typeGenerator configurator itself can be used with collections as well:

class Foo
class Bar(
    val list: List<Foo>,
    val set: Set<String>,
    val map: Map<String, Int>

val bar = faker.randomProvider.randomClassInstance<Bar> {
    typeGenerator { emptyList<Foo>() }
    typeGenerator { setOf("one", "two", "fortytwo") }
    typeGenerator { mapOf("pwd" to 12177) }
assertEquals(bar.list, emptyList<Foo>())
assertEquals(bar.set, setOf("one", "two", "fortytwo"))
assertEquals(bar.map, mapOf("pwd" to 12177))


Random Everything

Faker provides its wrapper functions around java.util.Random (with some additional functionality that is not covered by java.util.Random) through Faker().random property.

Wrappers around java.util.Random

faker.random.nextInt(bound = 100)
faker.random.nextInt(min = 100, max = 999)
faker.random.nextInt(intRange = (0..99))
faker.random.nextLetter(upper = false)

Random Enum Instance

enum class Foo {

faker.random.nextEnum(enum = Foo::class.java)
faker.random.nextEnum(values = Foo.values())
faker.random.nextEnum(enum = Foo::class.java) { it != Foo.ONE }
faker.random.nextEnum<Foo>(excludeName = "ONE")

Random Strings

    length = 42,
    numericalChars = false

    length = 24,
    locale = Locale.forLanguageTag("nb-NO"),
    indexChars = true,
    auxiliaryChars = true,
    punctuationChars = true,
    numericalChars = true,

Random sub-lists and sub-sets

val list = List(100) { it }
faker.random.randomSublist(list, size = 10, shuffled = true)
faker.random.randomSublist(list, sizeRange = 6..42, shuffled = true)

val set = setOf(*List(100) { it }.toTypedArray())
faker.random.randomSubset(set, size = 10, shuffled = true)
faker.random.randomSubset(set, sizeRange = 66..99, shuffled = true)

Random element from a list/array

val list = listOf(1, 2, 3)

Random UUID



Random Strings from Templates

Faker's StringProvider allows for replacing certain user-defined parts of strings with randomly generated chars (letters and digits), as well as generating strings from regex expressions. The following functions are available withing the Faker().string:

faker.string.numerify("123###").all { it.isDigit() } shouldBe true
faker.string.letterify("foo???").all { it.isLetter() } shouldBe true
faker.string.letterify("???BAR", true).all { it.isUpperCase() } shouldBe true
faker.string.letterify("???bar", false).all { it.isLowerCase() } shouldBe true
faker.string.regexify("""\d{42}""").all { it.isDigit() } shouldBe true
faker.string.regexify("""\d{42}""").length shouldBe 42