Kotest 시스템 확장(System Extensions)

Kotest의 시스템 확장(System Extensions)은 Java의 java.lang.System 클래스와 관련하여 시스템 호출에 대한 Assertion을 제공한다. 이 확장은 시스템 호출에 대한 예외를 테스트하고, 시스템 출력 또는 시스템 종료와 같은 동작을 확인하는 데 사용된다.

시스템 확장

java.lang.System을 사용하는 코드를 테스트해야 하는 경우, Kotest는 시스템을 변경하고 각 테스트 후에 복원할 수 있는 확장 기능을 제공한다. 이 확장은 JVM에서만 사용할 수 있다.

이 확장을 사용하려면 프로젝트에 종속성을 추가한다:

io.kotest:kotest-extensions-jvm:${version}

시스템 환경

시스템 환경 확장을 사용하면 시스템 환경이 어떻게 작동하는지 시뮬레이션할 수 있다. 즉, System.getenv()에서 얻는 것을 시뮬레이션할 수 있다.

Kotest는 특정 범위의 시스템 환경을 제공하는 몇 가지 확장 함수를 제공한다:

withEnvironment("FooKey", "BarValue") {
    System.getenv("FooKey") shouldBe "BarValue" // System environment overridden!
}

이 확장 기능에서는 Map이나 Pair 목록을 통해 여러 값을 사용할 수도 있다.

withEnvironment(mapOf("FooKey" to "BarValue", "BarKey" to "FooValue")) {
  // Use FooKey and BarKey
}

이 함수는 키와 값이 현재 환경에 없는 경우 추가하고, 있는 경우 재정의한다. 함수에 의해 건드리지 않은 키는 환경에 그대로 유지되며 변경되지 않는다.

확장 함수 대신 제공된 리스너를 사용하여 더 넓은 범위에서 이러한 기능을 적용할 수도 있다. Spec/Per 테스트 레벨에 대한 대안과 프로젝트 레벨에 대한 대안이 있다.

import io.kotest.core.spec.style.FreeSpec
import io.kotest.extensions.system.SystemEnvironmentTestListener
import io.kotest.matchers.shouldBe

class MyTest : FreeSpec() {

    override fun listeners() = listOf(SystemEnvironmentTestListener("foo", "bar"))

    init {
        "MyTest" {
            System.getenv("foo") shouldBe "bar"
        }
    }
}
import io.kotest.core.config.AbstractProjectConfig
import io.kotest.extensions.system.SystemEnvironmentProjectListener

class ProjectConfig : AbstractProjectConfig() {
    override fun listeners() = listOf(SystemEnvironmentProjectListener("foo", "bar"))
}

시스템 프로퍼티 확장

환경 확장과 같은 방식으로 시스템 프로퍼티(System.getProperties())를 재정의할 수 있다:

withSystemProperty("foo", "bar") {
    System.getProperty("foo") shouldBe "bar"
}

그리고 리스너으로도 제공된다:

import io.kotest.core.spec.style.FreeSpec
import io.kotest.extensions.system.SystemPropertyTestListener
import io.kotest.matchers.shouldBe

class MyTest : FreeSpec() {

    override fun listeners() = listOf(SystemPropertyTestListener("foo", "bar"))

    init {
        "MyTest" {
            System.getProperty("foo") shouldBe "bar"
        }
    }
}

시스템 보안 관리자

마찬가지로 시스템 보안 관리자를 사용하면 시스템 보안 관리자(System.getSecurityManager())를 재정의할 수 있다.

withSecurityManager(myManager) {
    // Usage of security manager
}

그리고 리스너으로도 제공된다:

import io.kotest.core.spec.style.FreeSpec
import io.kotest.extensions.system.SecurityManagerListener

class MyTest : FreeSpec() {

    override fun listeners() = listOf(SecurityManagerListener(myManager))

    init {
        // Use my security manager
    }
}

시스템 종료 확장

때때로 코드가 System.exit를 호출하는지 테스트하고 싶을 때가 있다. 이를 위해 시스템 종료 리스너를 사용할 수 있다. 리스너는 System.exit가 호출될 때 예외를 던지므로 이를 포착하고 확인할 수 있다:

import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.FreeSpec
import io.kotest.extensions.system.SpecSystemExitListener
import io.kotest.extensions.system.SystemExitException
import io.kotest.matchers.shouldBe

class MyTest : FreeSpec() {

    override fun listeners() = listOf(SpecSystemExitListener)

    init {
        "Catch exception" {
            val thrown: SystemExitException = shouldThrow<SystemExitException> {
                System.exit(22)
            }

            thrown.exitCode shouldBe 22
        }
    }
}

no-stdout/no-stderr 리스너

디버그 메시지를 남기지 않았거나 로깅에 항상 로거를 사용하고 있는지 확인하고 싶을 수도 있다.

이를 위해 Kotest는 NoSystemOutListenerNoSystemErrListener를 제공한다. 이러한 리스너는 각각 System.out 또는 System.err에 메시지를 바로 출력하는 것을 허용하지 않는다:

    // In Project or in Spec
    override fun listeners() = listOf(NoSystemOutListener, NoSystemErrListener)

Locale/Timezone 리스너

일부 코드는 기본 Locale 및 Timezone를 사용하거나 이에 민감하다. 시스템 기본값을 직접 조작하는 대신 Kotest가 대신 처리해 준다.

withDefaultLocale(Locale.FRANCE) {
  println("My locale is now France! Très bien!")
}

withDefaultTimeZone(TimeZone.getTimeZone(ZoneId.of("America/Sao_Paulo"))) {
  println("My timezone is now America/Sao_Paulo! Muito bem!")
}

그리고 리스너으로도 제공된다:

// In Project or in Spec
override fun listeners() = listOf(
    LocaleTestListener(Locale.FRANCE),
    TimeZoneTestListener(TimeZone.getTimeZone(ZoneId.of("America/Sao_Paulo")))
)

참조




최종 수정 : 2024-04-21