visible true

技術的なメモを書く

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とかもできそう。 もっと違う方法あるきもする