Zum Hauptinhalt springen

🎯 Assertion

📖 Was ist eine Assertion?

Assertion ist die Validierung der erwarteten Ergebnisse in Tests. Mit Kotest können Sie lesbarere und leistungsfähigere Validierungen durchführen!

💡 Kotest-Konfiguration

build.gradle.kts

dependencies {
testImplementation("io.kotest:kotest-runner-junit5:5.5.0")
testImplementation("io.kotest:kotest-assertions-core:5.5.0")
}

🎯 Grundlegende Assertions

shouldBe

import io.kotest.matchers.shouldBe
import io.kotest.core.spec.style.StringSpec

class BasicAssertionTest : StringSpec({
"숫자 비교" {
val result = 2 + 3
result shouldBe 5
}

"문자열 비교" {
val name = "Kotlin"
name shouldBe "Kotlin"
}

"불린 검증" {
val isValid = true
isValid shouldBe true
}
})

Verschiedene Matcher

import io.kotest.matchers.*
import io.kotest.matchers.string.*

class MatcherTest : StringSpec({
"다양한 비교" {
// 동등성
5 shouldBe 5
5 shouldNotBe 6

// 크기 비교
10 shouldBeGreaterThan 5
3 shouldBeLessThan 10
5 shouldBeInRange 1..10

// 문자열
"hello" shouldStartWith "he"
"world" shouldEndWith "ld"
"kotlin" shouldContain "otl"
"test" shouldHaveLength 4
}
})

🎨 Collection Assertions

Listen-Validierung

import io.kotest.matchers.collections.*

class CollectionTest : StringSpec({
"리스트 검증" {
val numbers = listOf(1, 2, 3, 4, 5)

// 크기
numbers shouldHaveSize 5
numbers.shouldNotBeEmpty()

// 포함
numbers shouldContain 3
numbers shouldContainAll listOf(1, 3, 5)

// 순서
numbers.shouldBeSorted()

// 조건
numbers.forAll { it shouldBeGreaterThan 0 }
numbers.forAtLeastOne { it shouldBe 3 }
}
})

Map-Validierung

class MapTest : StringSpec({
"Map 검증" {
val map = mapOf("name" to "홍길동", "age" to "25")

// 키/값 존재
map shouldContainKey "name"
map shouldContainValue "홍길동"

// 항목 검증
map shouldContain ("name" to "홍길동")

// 크기
map shouldHaveSize 2
}
})

🔥 Praktische Beispiele

Benutzer-Validierung

data class User(
val name: String,
val email: String,
val age: Int
)

class UserTest : StringSpec({
"사용자 정보 검증" {
val user = User("홍길동", "hong@example.com", 25)

user.name shouldBe "홍길동"
user.email shouldContain "@"
user.age shouldBeInRange 1..100
}

"이메일 형식 검증" {
val user = User("김철수", "kim@test.com", 30)

user.email shouldStartWith "kim"
user.email shouldEndWith ".com"
user.email shouldMatch Regex("\\w+@\\w+\\.\\w+")
}
})

Bestellungs-Validierung

data class Order(
val id: String,
val items: List<Item>,
val total: Double
)

data class Item(val name: String, val price: Double)

class OrderTest : StringSpec({
"주문 검증" {
val order = Order(
id = "ORDER-001",
items = listOf(
Item("사과", 1000.0),
Item("바나나", 1500.0)
),
total = 2500.0
)

// ID 검증
order.id shouldStartWith "ORDER-"

// 아이템 검증
order.items shouldHaveSize 2
order.items.forAll { it.price shouldBeGreaterThan 0.0 }

// 합계 검증
order.total shouldBe 2500.0
}
})

🛡️ Exception Assertions

Validierung von Ausnahmen

import io.kotest.assertions.throwables.*

class ExceptionTest : StringSpec({
"예외 발생 검증" {
shouldThrow<IllegalArgumentException> {
validateAge(-1)
}
}

"예외 메시지 검증" {
val exception = shouldThrow<IllegalArgumentException> {
validateAge(-1)
}

exception.message shouldBe "나이는 0 이상이어야 합니다"
}

"예외 발생 안함" {
shouldNotThrowAny {
validateAge(25)
}
}
})

fun validateAge(age: Int) {
require(age >= 0) { "나이는 0 이상이어야 합니다" }
}

🎯 Soft Assertions

Mehrere Validierungen auf einmal

import io.kotest.assertions.assertSoftly

class SoftAssertionTest : StringSpec({
"Soft Assertion" {
val user = User("홍길동", "hong@example.com", 25)

assertSoftly(user) {
name shouldBe "홍길동"
email shouldContain "@"
age shouldBeInRange 20..30
}
}

"모든 실패를 한번에 보기" {
assertSoftly {
1 shouldBe 2 // 실패해도 계속
"hello" shouldBe "world" // 이것도 체크
true shouldBe false // 이것도 체크
}
// 모든 실패를 한번에 보여줌
}
})

🔧 Benutzerdefinierte Matcher

Ihre eigene Validierung

import io.kotest.matchers.Matcher
import io.kotest.matchers.MatcherResult
import io.kotest.matchers.should

fun beEven() = Matcher<Int> { value ->
MatcherResult(
value % 2 == 0,
{ "$value는 짝수여야 합니다" },
{ "$value는 짝수가 아니어야 합니다" }
)
}

fun bePositive() = Matcher<Int> { value ->
MatcherResult(
value > 0,
{ "$value는 양수여야 합니다" },
{ "$value는 양수가 아니어야 합니다" }
)
}

class CustomMatcherTest : StringSpec({
"커스텀 Matcher" {
4 should beEven()
10 should bePositive()
}
})

🎨 Datenklassen-Vergleich

Teilweiser Vergleich

data class Person(
val name: String,
val age: Int,
val address: String
)

class PersonTest : StringSpec({
"데이터 클래스 비교" {
val person = Person("홍길동", 25, "서울")

// 전체 비교
person shouldBe Person("홍길동", 25, "서울")

// 부분 비교
person.name shouldBe "홍길동"
person.age shouldBeInRange 20..30
}
})

🔥 Praktische Muster

Bereichs-Validierung

class RangeTest : StringSpec({
"범위 검증" {
val score = 85

score shouldBeInRange 0..100
score shouldBeGreaterThan 60
score shouldBeLessThan 90
}

"날짜 범위" {
val today = "2024-12-25"

today shouldBeGreaterThan "2024-01-01"
today shouldBeLessThan "2025-01-01"
}
})

Typ-Validierung

import io.kotest.matchers.types.*

class TypeTest : StringSpec({
"타입 검증" {
val value: Any = "hello"

value.shouldBeInstanceOf<String>()
value shouldBe instanceOf<String>()
}

"Null 검증" {
val nullValue: String? = null
val nonNull: String? = "test"

nullValue.shouldBeNull()
nonNull.shouldNotBeNull()
}
})

Validierung mit regulären Ausdrücken

class RegexTest : StringSpec({
"정규식 매칭" {
val email = "hong@example.com"

email shouldMatch Regex("\\w+@\\w+\\.\\w+")
}

"전화번호 검증" {
val phone = "010-1234-5678"

phone shouldMatch Regex("\\d{3}-\\d{4}-\\d{4}")
}
})

🤔 Häufig gestellte Fragen

Q1. shouldBe vs assertEquals?

A: shouldBe ist lesbarer!

// JUnit
assertEquals(5, result)

// Kotest
result shouldBe 5 // 더 자연스러움

Q2. Anpassen von Fehlermeldungen?

A: Verwenden Sie withClue!

import io.kotest.assertions.withClue

class ClueTest : StringSpec({
"커스텀 메시지" {
withClue("사용자 나이 검증 실패") {
25 shouldBeInRange 20..30
}
}
})

Q3. Nur eine von mehreren Bedingungen?

A: Verwenden Sie anyOf!

import io.kotest.matchers.or

class AnyOfTest : StringSpec({
"여러 조건 중 하나" {
val value = 5

value shouldBe (3 or 5 or 7)
}
})

🎬 Fazit

Zuverlässige Validierung mit leistungsstarken Assertions!

Zusammenfassung:
✅ Prägnante Validierung mit shouldBe
✅ Verschiedene Matcher nutzen
✅ Alles auf einmal mit Soft Assertions
✅ Benutzerdefinierte Matcher schreiben
✅ Typ-/Bereichs-/Regex-Validierung

Nächster Schritt: Erfahren Sie mehr über Test Doubles in Mocking!