Reputation: 1679
I'm trying to write KotlinTest tests running on JUnit5, with the Describe Spec style.
When I need to initialize the same variable for some tests, @BeforeEach does not work inside DescribeSpec.
How can initialize data before each test?
class BlockchainUT : DescribeSpec({
var blockchain = Blockchain()
@BeforeEach
fun beforeEach() {
blockchain = Blockchain()
blockchain.addBlock(listOf("foo1", "bar1"))
blockchain.addBlock(listOf("foo2", "bar2"))
blockchain.addBlock(listOf("foo3", "bar3"))
}
describe("isValidChain()") {
context("when the chain does not start with the genesis block") {
blockchain.chain[0] = Block(
System.currentTimeMillis(),
"---",
"xxx",
listOf("foo", "bar"))
it("returns false") {
Blockchain.isValid(blockchain) shouldBe false
}
}
context("when the chain starts with the genesis block and has multiple blocks") {
context("and a lastHash reference has changed returns false") {
blockchain.chain[2] = Block(
blockchain.chain[2].timestamp,
"broken-lastHash",
blockchain.chain[2].hash,
blockchain.chain[2].data)
it("returns false") {
Blockchain.isValid(blockchain) shouldBe false
}
}
context("and the chain contains a block with an invalid field") {
blockchain.chain[2] = Block(
blockchain.chain[2].timestamp,
blockchain.chain[2].lastHash,
blockchain.chain[2].hash,
listOf("some-bad-and-evil-data"))
it("returns false") {
Blockchain.isValid(blockchain) shouldBe false
}
}
}
}
})
Upvotes: 4
Views: 2408
Reputation: 1679
On the new version of KotlinTest 3.3 there are new Listeners to define beforeTest
, afterTest
, beforeSpec
and so on.
In this case a posible solution should be:
class BlockchainUT : DescribeSpec(), TestListener {
var blockchain = Blockchain()
override fun beforeTest(describe: TestCase): Unit {
blockchain = Blockchain()
blockchain.addBlock(listOf("foo1", "bar1"))
blockchain.addBlock(listOf("foo2", "bar2"))
blockchain.addBlock(listOf("foo3", "bar3"))
}
init {
describe("isValidChain()") {
context("when the chain starts with the genesis block and has multiple blocks") {
context("and a lastHash reference has changed returns false") {
blockchain.chain[2] = Block(
blockchain.chain[2].timestamp,
"broken-lastHash",
blockchain.chain[2].hash,
blockchain.chain[2].data)
it("returns false") {
Blockchain.isValid(blockchain) shouldBe false
}
}
context("and the chain contains a block with an invalid field") {
blockchain.chain[2] = Block(
blockchain.chain[2].timestamp,
blockchain.chain[2].lastHash,
blockchain.chain[2].hash,
listOf("some-bad-and-evil-data"))
it("returns false") {
Blockchain.isValid(blockchain) shouldBe false
}
}
context("and the chain does not contain any invalid blocks") {
it("returns true") {
Blockchain.isValid(blockchain) shouldBe true
}
}
}
}
}
}
Also can be solved using the new Isolation Modes, defining the isolation mode to InstancePerLeaf
. From io.kotlintest.IsolationMode
javadoc:
A new instance of the [Spec] class is instantiated for every
[TestCase] - both containers and leaf tests - and they are
executed once the previous test has completed.
For example, in the following test plan:
"this test" {
println("a")
"nested test" {
println("b")
}
"nested test 2" {
println("c")
}
}
The output will be:
a
a
b
a
c
class BlockchainUT : DescribeSpec(){
override fun isolationMode() = IsolationMode.InstancePerTest
describe("isValidChain()") {
context("when the chain starts with the genesis block and has multiple blocks") {
var blockchain = Blockchain()
blockchain.addBlock(listOf("foo1", "bar1"))
blockchain.addBlock(listOf("foo2", "bar2"))
blockchain.addBlock(listOf("foo3", "bar3"))
context("and a lastHash reference has changed returns false") {
blockchain.chain[2] = Block(
blockchain.chain[2].timestamp,
"broken-lastHash",
blockchain.chain[2].hash,
blockchain.chain[2].data)
it("returns false") {
Blockchain.isValid(blockchain) shouldBe false
}
}
context("and the chain contains a block with an invalid field") {
blockchain.chain[2] = Block(
blockchain.chain[2].timestamp,
blockchain.chain[2].lastHash,
blockchain.chain[2].hash,
listOf("some-bad-and-evil-data"))
it("returns false") {
Blockchain.isValid(blockchain) shouldBe false
}
}
context("and the chain does not contain any invalid blocks") {
it("returns true") {
Blockchain.isValid(blockchain) shouldBe true
}
}
}
}
}
}
Upvotes: 4