Kotest JSON マッチャー(JSON Matchers)
概要
JSON マッチャーを使用するには、ビルドに testImplementation("io.kotest.extensions:kotest-assertions-json:<version>") を追加する必要がある。
基本マッチャー
| マッチャー | 説明 | 対象 |
|---|---|---|
shouldBeValidJson |
指定した文字列が有効な JSON としてパースできることを確認する。 | Multiplatform |
shouldBeJsonObject |
文字列が有効な JSON オブジェクトであることを確認する。 | Multiplatform |
shouldBeJsonArray |
文字列が有効な JSON 配列であることを確認する。 | Multiplatform |
コンテンツベースのマッチング
詳しくは JSON コンテンツマッチングを参照する。
| マッチャー | 説明 | 対象 |
|---|---|---|
shouldEqualJson |
文字列が指定した JSON 構造と一致することを確認する。 | Multiplatform |
shouldEqualSpecifiedJson |
文字列が指定した JSON 構造と一致することを確認するが、指定されていない追加プロパティを許可する。 | Multiplatform |
shouldContainJsonKey |
文字列が JSON であり、指定した JSON パスを含むことを確認する。 | JVM |
shouldContainJsonKeyValue |
文字列が JSON であり、指定した値を持つ指定 JSON パスを含むことを確認する。 | JVM |
shouldMatchJsonResource |
文字列が指定したテストリソースの JSON コンテンツと一致することを確認する。 | JVM |
スキーマ検証
| マッチャー | 説明 | 対象 |
|---|---|---|
shouldMatchSchema |
String または kotlinx.serialization.JsonElement が JsonSchema と一致することを確認する。スキーマ構成の詳細は以下を参照する。 |
Multiplatform |
JSON コンテンツマッチング
このモジュールは JVM および JS ターゲットで使用できる。
shouldEqualJson
json.shouldEqualJson(other) は、左側が右側と同じ JSON 構造であることを確認する。
このマッチャーは、異なるフォーマットや異なるキー順序を許可する。
たとえば、次の 2 つの JSON 文字列は同じものと見なされる。
{
"name": "sam",
"location": "chicago",
"age" : 41
}
そして
{ "age" : 41, "name": "sam", "location": "chicago" }
このマッチャーの反対は shouldNotEqualJson であり、2 つの JSON 文字列が同じものと見なされる場合にエラーになる。
compareJsonOptions
shouldEqualJson は、JSON 比較の動作を切り替えるためのフラグを持つ CompareJsonOptions 型の追加パラメータをサポートする。
使用法:
オプションは次のようにインラインで指定できる。
a.shouldEqualJson(b, compareJsonOptions { arrayOrder = ArrayOrder.Strict })
もう 1 つの方法は、必要な比較動作を定義することである。
val myOptions = compareJsonOptions {
typeCoercion = TypeCoercion.Enabled
arrayOrder = ArrayOrder.Lenient
}
infix fun String.lenientShouldEqualJson(other: String) = this.shouldEqualJson(other, myOptions)
"[1, 2]" lenientShouldEqualJson "[2, 1]" // This will pass
Parameters
| 名前 | 目的 | 可能な値 | デフォルト |
|---|---|---|---|
PropertyOrder |
比較時に JSON オブジェクトのプロパティ順序を考慮するかを決定する。 | PropertyOrder.Strict, PropertyOrder.Lenient |
PropertyOrder.Lenient; プロパティ順序は重要ではない。 |
ArrayOrder |
比較時に JSON 配列の要素順序を考慮するかを決定する。 | ArrayOrder.Strict, ArrayOrder.Lenient |
ArrayOrder.Strict; 要素順序は重要である。 |
FieldComparison |
actualJSON が expected と比較して追加プロパティを含む場合に比較を失敗させるかを決定する。 |
FieldComparison.Strict, FieldComparison.Lenient |
FieldComparison.Strict; 追加プロパティによって不一致になる。 |
NumberFormat |
数値形式について厳密に比較するかを決定する。たとえば 100.0 と 100 を同じと見なすかどうかである。 |
NumberFormat.Strict, NumberFormat.Lenient |
NumberFormat.Lenient; 数値形式は重要ではない。 |
TypeCoercion |
文字列に数値やブール値が含まれる場合などに、型を強制変換するかを決定する。 | TypeCoercion.Enabled, TypeCoercion.Disabled |
TypeCoercion.Disabled; 型は強制変換されない。 |
対象: Multiplatform
shouldEqualSpecifiedJson
shouldEqualJson の別名で、デフォルトオプションは FieldComparison だけが異なり、FieldComparison.Lenient に設定される。
val a = """ { "a": true, "date": "2019-11-03" } """
val b = """ { "a": true } """
// this would pass
a shouldEqualSpecifiedJson b
// this would fail
a shouldEqualJson b
対象: Multiplatform
shouldContainJsonKey
json.shouldContainJsonKey("$.json.path") は、JSON 文字列に指定した JSON パスが含まれることを確認する。
反対のマッチャーは shouldNotContainJsonKey で、JSON 文字列に指定した JSON パスが含まれる場合にエラーになる。
対象: JVM
shouldContainJsonKeyValue
str.shouldContainJsonKeyValue("$.json.path", value) は、JSON 文字列に特定の値を持つ JSON パスが含まれることを確認する。
反対のマッチャーは shouldNotContainJsonKeyValue で、指定した JSON パスに指定した値が含まれる場合にエラーになる。
対象: JVM
shouldMatchJsonResource
json.shouldMatchJsonResource("/file.json") は、プロパティ順序とフォーマットを無視して、JSON が既存のテストリソース /file.json と同じであることを確認する。
対象: JVM
JSON スキーママッチャー
| マッチャー | 説明 | 対象 |
|---|---|---|
shouldMatchSchema |
String または kotlinx.serialization.JsonElement が JsonSchema と一致することを確認する。スキーマ構成の詳細は以下を参照する。 |
Multiplatform |
JSON Schema のサブセットは、テキストスキーマをパースして定義できる。
例:
val parsedSchema = parseSchema(
"""
{
"$id": "https://example.com/geographical-location.schema.json", // will be ignored
"$schema": "https://json-schema.org/draft/2020-12/schema", // will be ignored
"title": "Longitude and Latitude Values", // will be ignored
"description": "A geographical coordinate.", // will be ignored
"required": [ "latitude", "longitude" ],
"type": "object",
"properties": {
"latitude": {
"type": "number",
"minimum": -90,
"maximum": 90
},
"longitude": {
"type": "number",
"minimum": -180,
"maximum": 180
}
}
}
"""
)
または Kotest の組み込み DSL を使用する。
val addressSchema = jsonSchema {
obj { // object is reserved, obj was chosen over jsonObject for brevity but could be changed ofc, or jsonObject could be added as alternative.
withProperty("street", required = true) { string() }
withProperty("zipCode", required = true) {
integer {
beEven() and beInRange(10000..99999) // supports constructing a matcher that will be used to test values
}
}
additionalProperties = false // triggers failure if other properties are defined in actual
}
}
val personSchema = jsonSchema {
obj {
withProperty("name", required = true) { string() }
withProperty("address") { addressSchema() } // Schemas can re-use other schemas 🎉
}
}
スキーマ構築
配列
配列は順序付きの要素に使用される。JSON では、配列の各要素が異なる型を持つことができる。
Length (minItems and maxItems)
配列の長さは minItems と maxItems キーワードで指定できる。各キーワードの値は非負の数でなければならず、デフォルトは 0 と Int.MAX_VALUE である。
val lengthBoundedSchema = jsonSchema {
array(minItems = 0, maxItems = 1) { number() }
}
Uniqueness
スキーマは、配列の各項目が一意であることを確認できる。uniqueItems キーワードを true に設定するだけでよい。
val uniqueArray = jsonSchema {
array(uniqueItems = true) { number() }
}
⚠️ Kotest は現在、JSON Schema のサブセットのみをサポートしている。現在サポートされていない項目は次のとおりである。
- $defs and $refs
- Recursive schemas
- Parsing of schema composition
- string.format
- array.prefixItems,
- array.contains,
- array.items = false
- array.maxContains
- array.minContains
- array.uniqueItems
- enum
検証
スキーマが定義されると、それを基準に String と kotlinx.serialization.JsonElement を検証できる。
"{}" shouldMatchSchema personSchema
// fails with:
// $.name => Expected string, but was undefined
""" { "name": "Emil", "age": 34 } """
// Passes, since address isn't required and `additionalProperties` are allowed