KotlinTestのBehaviorSpecでGivenの単位でBeforeしたい
KotlinTestいいんですよね。 AndroidじゃなくてSpringBootで使ってるんですが。 Androidでも使えるかな?どうかな?まだ無理っぽい。
beforeSpecはSpec開始時に一度だけしか実行されない
KotlinTestのSpec群はbeforeなんとか、afterなんとか系の関数を持っていて、オーバーライドして使うんですが、例えばbeforeSpec(spec: Spec)なんかだと、 Spec開始時に一度だけしか実行されないので、Given単位でDBの状態変えたいなって時に使えないんですよね。
beforeTestでisTopLevelを見る
別のタイミングとしてbeforeTest(testCase: TestCase)というのがあるんですが、こっちはGiven, When, Thenの全部で呼ばれる。これだとGivenでDB作ってもWhen行く時には消えてしまう。 beforeGivenとかないんかなと思ったけどないらしい。
beforeTestにはTestCaseが渡ってくる。TestCaseにいろんな情報があるので、これを使って判定すると良さそうってことでいろいろガチャガチャやってたら、どうもGivenはisTopLevelがtrueになるらしいということがわかった。
ということでbeforeTestでこんな感じでやると良さそう。
class TodoResourceSpec( val mockMvc: MockMvc, val dataSource: DataSource ) : BehaviorSpec() { override fun beforeTest(testCase: TestCase) { if (testCase.isTopLevel()) { // Givenの時だけtrueになる dbSetup(dataSource) { truncate("todo") }.launch() } } init { Given("I have empty todo list") { // ここと When("get todo list") { val result = mockMvc.perform( get("/api/todo") .contentType(MediaType.APPLICATION_JSON) ) Then("should return empty list") { result.andExpect(status().isOk) .andExpect(content().json("""[]""")) } } } Given("I have a one todo") { // ここでtruncateが走る // 省略 } } }
おわり
BehaviorSpecは抽象クラスなので、継承してbeforeGivenとか関数生やしてもいいかもしれないと思った。 TestCase#nameにはWhenとかThenとか文字列で書いてあるのでそれを見てbeforeWhenとかもできそう。 もっと違う方法あるきもする