KarateでのAPIテストと同時にAssertJ-DBでデータの確認もやりたい
はじめに
Karateを使うとWeb APIのリクエスト&レスポンスのテストがとてもいい感じにできるが、そうすると今度は「POSTされたデータがちゃんとDBに入っているかどうか」とかも確認したくなってきてしまうもの。 そこでKarateでのテストシナリオ実行の際、AssertJ-DBでのデータのアサーションが行われるようにしてみる*1。
環境
- Spring Boot 2.5.0
- Karate (karate-junit5) 1.0.1
- AssertJ-DB 2.0.2
ポイント
Karateのfeatureファイルでは、Java.type('パッケージ+クラス名')
でJavaのクラスを参照できる。
これを利用し、あらかじめDBのテスト用メソッドをAssertJ-DBで書いておいて、それをfeatureファイルから呼び出すようにする。
サンプルコード全体は下記のとおり。
やり方
JavaでDBのアサーションを行うメソッドを定義する
テストランナーのクラスにDBのアサーションを行うメソッドを定義しておく。下記サンプルの public static void assertTable(String expectedMessage)
がそれ。
package demo; // ... @SpringBootTest(classes = DemoApplication.class) public class DemoTestRunner { private static DataSource dataSource; @Autowired private void setDataSource(DataSource dataSource) { DemoTestRunner.dataSource = dataSource; } @Karate.Test Karate testAll() { return Karate.run().relativeTo(getClass()); } public static void assertTable(String expectedMessage) { var table = new Table(dataSource, "messages"); assertThat(table).hasNumberOfRows(1) .row(0) .column("message").value().isEqualTo(expectedMessage); } }
Java.type()
で使いたいのでメソッドは public static
にする必要があり、それに合わせて DataSource
をstaticフィールドにしている。
staticなDataSourceをインジェクションできるようにするため、 setDataSource()
はだいぶ無理やり感がある…。
DBのアサーション自体は普通にAssertJ-DBで書けばよい。
featureファイルのシナリオでJavaのメソッドを呼び出す
こんな感じ。
Feature: Demo Background: * url baseUrl * def DemoTestRunner = Java.type('demo.DemoTestRunner') Scenario: Add a message Given path '/' And request { "message": "Hello" } When method post Then status 200 And DemoTestRunner.assertTable('Hello') Scenario: Find messages # ...
Background
で def DemoTestRunner = Java.type('demo.DemoTestRunner')
することで、引数で指定されたJavaのクラス(今回は DemoTestRunner
)が使えるようにしておく。
シナリオでは DemoTestRunner.assertTable('Hello')
のようにしてメソッドを呼び出す。
実行してみる
いつもどおりテストランナーのクラス(今回は DemoTestRunner
)を実行すればよい。
IntelliJ IDEAだとテスト結果は普通にこんな感じで出てくる。
HTMLレポートも出てくる。
試しにこんな感じでテストをわざと失敗させてみると…
Scenario: Add a message Given path '/' And request { "message": "INVALID" } When method post Then status 200 And DemoTestRunner.assertTable('Hello')
失敗時の情報もちゃんと出てくる。よさそう。