factory-bot
allows you to cleanly create and maintain test data.
You can use it to define your own Factories/Generators and override this logic directly when instantiating the factories in your tests.
object UserFactory{
val validUser = UserSpec(
id = { UUID.randomUUID() },
name = { "Peter" }
)
val userWithAddress = validUser.copy(
address = { Addresses.validAddress() }
)
}
// in your tests
val user = UserFactory.validUser()
val martha = UserFactory.validUser(name = "Martha")
val userWithAddr
factory-bot
is intended as a clone of Ruby's fantastic factory_bot gem for Kotlin.
faktory-bot
generates boilerplate code using
the Kotlin Symbol Processing (KSP). Therefore, you
need to apply the ksp
gradle plugin and add the following dependencies to your build.gradle.kts
:
plugins {
kotlin("jvm") version "1.7.10"
// The following version must match with the kotlin version
id("com.google.devtools.ksp") version "1.7.10-1.0.7"
}
dependencies {
compileOnly("io.github.raphiz:faktory-bot-annotations:0.1.0")
ksp("io.github.raphiz:faktory-bot-processor:0.1.0")
}
// Make IDE aware of generated code, see also:
// https://kotlinlang.org/docs/ksp-quickstart.html#make-ide-aware-of-generated-code
kotlin {
sourceSets.main {
kotlin.srcDir("build/generated/ksp/main/kotlin")
}
}
**NOTE: ** The implementation of KSP is tied to a specific kotlin compiler version. Users of processors (
faktory-bot
is a processor) need to bump KSP version when bumping the compiler version in their project..faktory-bot
only depends on the KSP API, and should therefore work with most ksp and kotlin versions. If not, please open an issue.
Once the KSP setup is completed, the usage of faktory-bot
is straight forward.
First, add the @Faktory
annotation any class, for example:
@Faktory
data class User(val id: UUID, val name: String, val address: Address?)
faktory-bot
will now generate the following code for you:
public data class UserSpec(
public val id: () -> UUID,
public val name: () -> String,
public val address: () -> Address? = { null },
) {
public operator fun invoke(
id: UUID = this.id(),
name: String = this.name(),
address: Address? = this.address(),
): User = User(id = id, name = name, address = address,)
public fun create(
id: UUID = this.id(),
name: String = this.name(),
address: Address? = this.address(),
): User = User(id = id, name = name, address = address,)
}
The two generated methods, create
and invoke
do exactly the same. The latter is just for syntactic sugar (see example below).
Using this Faktroy, you can now simply create your own data factories
val validUser = UserSpec(
id = { UUID.randomUUID() },
name = { "Peter" }
)
and use them in your test (or for generating example/test data)
@Test
fun `it saves a user`() {
val user = validUser.create(name="Another name for my test")
// alternatively, using `invoke`
// val user = validUser()
userRepository.save(user)
val allUsers = userRepository.findAll()
assertThat(allUsers).containsExactly(user)
}
For more examples, checkout the example-app
.
The create()
methods are great to create objects. However, when writing tests that interact with a database, it would be nice to have an easy way to insert data. For this, faktory-bot
offers the withInsert
option on the @Faktory
annotation.
@Faktory(withInsert=true)
data class User(val id: UUID, val name: String, val address: Address?)
This will add a parameter to the generated Faktroy: A function used for persistence.
class UserRepositoryTest {
private val userRepository = UserRepository()
private val validUser = UserSpec(
faktoryInsertFn = userRepository::save,
id = { UUID.randomUUID() },
name = { "Peter" }
)
@Test
fun `it returns an inserted user`() {
val expectedUser = validUser.insert()
val allUsers = userRepository.findAll()
assertThat(allUsers).containsExactly(expectedUser)
}
}
This is just syntactic sugar to remove noise from your tests.
faktory-bot
is a factory_bot clone for Kotlin. The API is modeled as closely as possible to factory bot.
Therefore, best practices that apply to factory_bot also apply to faktory-bot
.
We welcome contributions to faktory-bot! If you would like to report a bug or request a feature, please open an issue. If you want to submit a pull request, please make sure to include tests for your changes.
faktory-bot is inspired by the following projects: