Kotlin测试,如何使用DescribeSpec测试风格运行BeforeEach

时间:2019-06-09 20:46:05

标签: kotlin kotlintest

我正在尝试使用KotlinTest编写在JUnit5上运行的Describe Spec style测试。

在某些测试中需要初始化相同的变量时,@ BeforeEach在DescribeSpec内不起作用。

在每次测试之前如何初始化数据?

<?xml version="1.0" encoding="UTF-8"?>
<X3D>
    <Scene>
        <Viewpoint description='Front view' orientation='0 1 0 1.57' position='8 0 0'/> 
        <Shape DEF='Front'>
            <IndexedFaceSet coordIndex='0 1 2 3 4 5 6 7' solid='false' convex='true'>
                <Coordinate DEF='Points' point='
                1 1 1
                1 1 2
                1 1 3
                1 1 4
                2 1 4
                2 1 3
                2 1 2
                2 1 1
                1 1 1'/> 
            </IndexedFaceSet>
            <Appearance>
                <Material diffuseColor="0 0 1" specularColor=".5 .5 .5" DEF="edgecolour" />
            </Appearance>
        </Shape>
    </Scene>
</X3D>

1 个答案:

答案 0 :(得分:2)

在新版本的KotlinTest 3.3中,新的Listeners定义了beforeTestafterTestbeforeSpec等。

在这种情况下,可能的解决方案应该是:

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
                    }
                }
            }
        }
    }
}

也可以使用新的Isolation Modes来解决,将隔离模式定义为InstancePerLeaf。来自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

  1. 最后移动要在每个[TestCase]中重复的代码
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
                    }
                }
            }
        }
    }
}