Prepared
Lazily-generated value unique to a test case.
Usage
This helper allows to declare values that are needed by multiple tests, whilst ensuring each test gets its own distinct instance. Within a given test, however, the value is always the same:
suite("Random integers") {
val randomInteger by prepared { random.nextInt() }
test("First test") {
println(randomInteger()) // some integer
println(randomInteger()) // the same integer
}
test("Second test") {
println(randomInteger()) // another integer
}
}
Prepared values are constructed lazily when they are accessed within a test. Because of this, they have access to the test's TestDsl and can suspend
.
For the specific use-case of generating random values, see random.
Comparison with other frameworks
Test frameworks usually provide a construct like @BeforeTest
or similar. These constructs allow to declare instantiation code that is run before tests, however:
they are implicitly used by tests: in a large test file, it is difficult to know which ones may impact the test (whereas, prepared values must always be referred to in the test),
they have implicit ordering relationships: some
@BeforeTest
may use the result from previous ones, which makes it hard to know if removing one will impact test results (whereas, prepared values explicitly depend on each other),they require the need of some kind of
lateinit
variable to store their state (whereas, prepared values' state is available in all test scopes),they are not compatible with coroutines.
Test frameworks also tend to provide a construct like @AfterTest
, but again, this is covered by cleanUp. Prepared values can use cleanUp as well:
val database by prepared(Dispatchers.IO) {
val db = Database.connect()
cleanUp("Disconnect from the database") {
db.close()
}
db
}
test("Test") {
// if a prepared value is accessed in a test, it is automatically cleaned at the end of the test
database().listTables()
}
Values are instantiated using the prepared helper.