気軽に楽しくプログラムと遊ぶ

自分が興味があってためになるかもって思う情報を提供しています。

Kotlin テスト関連ライブラリ

Kotest(Kotlinテストフレームワーク)

概要

  • Kotlinの言語仕様で書けるテストフレームワークJunitよりもコード量を減らせる
  • ネストして実装可能でどんなテストを書くかを継承させるSpecで変えられる

実装例

FunSpecを使った実装例。contextを使って階層構造を表現している。
アサーションとして、代表的なとしてshouldBe(イコールみたいなやつ。右辺になるべきとの表現)、shouldThrow(例外になるべき)などがある。

class CalcServiceFunSpecTest : FunSpec() {
    private val calc = Calc()

    init {
        context("CalcServiceTest") {
            context("正常系") {
                test("1 + 1 は2になる") {
                    calc.plus(1, 1) shouldBe 2
                }
            }
            context("異常系") {
                test("5 ÷ 0 は例外が投げられる") {
                    shouldThrow<ArithmeticException> { calc.divide(5, 0) }
                }
            }
        }
    }
}

MockK(ClassをMock化)

概要

Wire mock(スタブサーバー構築)

概要

  • WireMockを使用して開発環境にスタブサーバーを構築することで、外部サービスとの連携をモックすることができる。
  • マイクロサービスのシステムや、外部サービスを利用することが多い場合に有用

実装例

Junit5でWireMockを使用する方法

以下、参考URLから引用させて頂いて、Javaでの記載になっているので注意。

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;

class SampleTest {

    // programmaticモードでの利用は、@RegisterExtensionを付与したWireMockExtensionを定義(複数の設定で定義可)
    @RegisterExtension
    static WireMockExtension mock = WireMockExtension.newInstance()
            // HTTPSでかつポートを3000固定とする設定
            .options(WireMockConfiguration.wireMockConfig().httpDisabled(false).port(3000))
            .build();

    @Test
    void test() {
        // Getメソッドで指定URLのときに起動するMockサーバーを定義
        mock.stubFor(WireMock.get(WireMock.urlEqualTo("/some/thing?name=Bob"))
                .withQueryParam("name", WireMock.containing("Bob"))
                // ヘッダー設定
                .withHeader("Content-Type", WireMock.equalTo("application/json"))
                // スタブを複数定義する場合は、優先度を数値指定。1が最優先で2、3と次に優先される
                .atPriority(1)
                // レスポンス設定
                .willReturn(WireMock.aResponse()
                        .withHeader("Content-Type", "application/json")
                        .withBody("Hello world!")));
                         // レスポンスを外部ファイル化する際は、レスポンスボディを定義したファイルのパスを指定する
                         // .withBodyFile("clientTest/get001.json")));
    }

}

マッピングファイルでスタブを登録する方法

{
    // スタブを複数定義する場合は、優先度を数値指定。1が最優先で2、3と次に優先される
    "priority": 1,
    "request": {
        "method": "GET",
        "url": "/some/thing?name=Bob",
        "headers" : {
            "Content-Type": {
                "equalTo" : "application/json"
            }
        },
        "queryParameters" : {
            "name" : {
                "containing" : "Bob"
            }
        }
    },
    "response": {
        "status": 200,
        "body":  "Hello world!",
        // レスポンスを外部ファイル化する際は、レスポンスボディを定義したファイルのパスを指定する
        // "bodyFileName": "clientTest/get001.json",
        "headers": {
            "Content-Type": "application/json"
        }
    }
}

レスポンスを動的に返却する

Response Templatingという機能がある。
二重中括弧({{}})で囲むことで、ifなどの条件式をはじめとする様々なヘルパーを使用可能。

詳しくは以下を参照 Mock API Response Templating | WireMock

Testcontainers

概要

  • Testcontainersはテストコード上でdockerコンテナの起動や停止を制御可能
  • 完全にテストコードの中だけで完結し、非常に簡単に導入可能
  • Dockerコンテナで実行できるデータベースなどに対して軽量で使い捨て可能なインスタンス提供する

ライブラリ読み込み

TOMLファイルの[libraries]、[plugins]テーブルなどにtestcontainersBomの設定を定義

libs.versions.toml

[versions]
javaLanguageVersion = "21"

kotlin = "1.9.24"
springBoot = "3.3.0"
testcontainersBom = "1.20.1"

[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-spring = { id = "org.jetbrains.kotlin.plugin.spring", version.ref = "kotlin" }
spring-boot = { id = "org.springframework.boot", version.ref = "springBoot" }

[libraries]
testcontainers-bom = { module = "org.testcontainers:testcontainers-bom", version.ref = "testcontainersBom" }
org-testcontainers-mysql = { module = "org.testcontainers:mysql" }

利用時の注意点

  • docker-compose -dなどで事前にコンテナを立ててしまっていると、テスト実行時に同じportに同じコンテナを起動しようとしてエラーになるので、コンテナ起動済みの場合は停止してからテスト実行する
  • Rancher Desktopなどを使っている場合、管理者権限がないとコンテナ作成、停止ができないので、管理者権限でアクセスできるように設定変更しておく。
  • 「歯車」アイコン > Application > Administrative Access から、管理者権限をAccept(許可)にします

  翻译: