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 구조와 동일한지 확인한다.
이 매처는 다른 형식과 다른 키 순서를 허용한다.
예를 들어, 다음 두 개의 JSON 문자열은 동일한 것으로 간주된다:
{
"name": "sam",
"location": "chicago",
"age" : 41
}
그리고
{ "age" : 41, "name": "sam", "location": "chicago" }
이 매처의 반대는 shouldNotEqualJson
으로, 두 개의 JSON 문자열이 동일한 것으로 간주되면 오류가 발생한다.
compareJsonOptions
shouldEqualJson
은 JSON 비교의 동작을 토글하기 위해 다음 플래그를 지원하는 CompareJsonOptions
유형의 추가 매개 변수를 지원한다:
사용법:
옵션은 다음과 같이 인라인(inline)으로 지정할 수 있다.
a.shouldEqualJson(b, compareJsonOptions { arrayOrder = ArrayOrder.Strict })
또 다른 옵션은 다음과 같이 원하는 대로 비교 기능을 정의하는 것이다:
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 |
JSON 객체에 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 문자열에 지정된 JSON 경로에 지정된 값이 포함되어 있으면 오류가 발생한다.
대상: JVM
shouldMatchJsonResource
json.shouldMatchJsonResource("/file.json")
는 속성의 순서와 서식을 무시하고 JSON이 기존 테스트 리소스 /file.json
과 같은지 확인한다.
대상: JVM
JSON 스키마 매처
매처 | 설명 | 대상 |
---|---|---|
shouldMatchSchema |
String 또는 kotlinx.serialization.JsonElement 가 JsonSchema와 일치하는지 확인한다. 스키마 구성에 대한 자세한 내용은 아래 설명을 참조한다. |
Multiplatform |
JSON 스키마의 하위 집합은 텍스트 스키마를 파싱하여 정의할 수 있다.
예시:
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 스키마의 하위 집합만 지원한다. 현재 지원되지 않는 항목은 다음과 같다:
- $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