今回はZIOの単体テストを見ていきます。
バックエンド編のzio-httpで作成したApplicationService.postTest
が正しい値を返すことを確認するテストを行いたいと思います。
セットアップ
ZIOによる単体テストを行うために以下をbuild.sbt
へ追加します。
lazy val root = (project in file("."))
(中略)
libraryDependencies += "dev.zio" %% "zio-http" % "3.0.0-RC2",
libraryDependencies ++= Seq(
"dev.zio" %% "zio-test" % "2.0.17" % Test,
"dev.zio" %% "zio-test-sbt" % "2.0.17" % Test,
"dev.zio" %% "zio-test-magnolia" % "2.0.17" % Test
),
testFrameworks +=
new TestFramework("zio.test.sbt.ZTestFramework")
)
テストコード
テストコードについてはプロジェクトルートからsrc/test/scala
配下に配置します。
今回以下のファイル名と内容で配置します。
object TrainingSpec extends ZIOSpecDefault {
def spec: Spec[Any, Throwable] = suite("単体テストトレーニング")(
test("「postTest」が正しい値を返す") {
for {
test <- ZIO.succeed("test")
uri <- ZIO.fromEither(URL.decode("http://localhost:8080/postTest"))
req <- ZIO.attempt(
Request
.default(
Method.POST,
uri,
Body.fromString(
s"userName=$test"
)
)
)
res <- ApplicationService.postTest(req)
bodyString <- res.body.asString
} yield assertTrue(bodyString == s"あなたの名前は${test}です。")
}.provide(ApplicationServiceImpl.layer, Client.default)
)
}
これをsbt test
で実行するとテストが成功することが確かめられると思います。
また、IntelliJにZIOプラグインを導入されている方は以下の画像の赤枠のボタンからも実行でき、確認できるかと思います。
詳細部分について見ていきます。
ZIOSpecDefault
の継承
これまでのZIOプログラムの実行の際にはZIOAppDefault
を継承して実行してきましたが、単体テストの場合にはZIOSpecDefault
を継承します。
テスト項目設定
テスト項目の設定についてはsuite
関数、test
関数で行います。
suite
関数がテスト項目のグルーピングを担い、test
関数が個々のテストを表しています。
test
関数内にテストコードを書きます。
実処理部分
実処理部分についてはTestController
からApplicationService.postTest
関数が呼び出される場合自動的にRequest
が作成され、引数として渡されますが、今回の場合は自動的には渡されないため、実際のRequest
インタスタンスを模したものを作成し、代わりに渡しています。
アサーション
最終的なレスポンスボディの値が正しいものであるかの判定をassertTrue
関数で行っています。
DI
また、依存するオブジェクトについてDIを行う必要があるため、こちらについても通常の場合と同様にprovide
関数によりDIを行っています。
終わりに
今回はZIOの単体テストについて見てきました。
今回の記事で終わりです。
ご意見、ご感想、誤っているところなどありましたらお気軽にご連絡頂ければ幸いです。
それでは失礼します。
演習
- 今回の単体テストの例について実際に動かし、挙動を確かめてください。
- 解答例は以下になります。
https://github.com/hatuda/zio-practice/tree/CHAPTER9
- 解答例は以下になります。