본문 바로가기

Programming!

runCatching - kotlin

코틀린 예외처리를 보다가 흠.. 이런게 있구나.. 하고 남김.

 

 

특정 클래스에서 숫자형 문자를 반환하고 반환된 문자를 Int형으로 변경하는 상황으로 테스트코드 작성.

 

internal class TextNumber {
    // 임의 Throw
    fun getThrow() : String {
        throw RuntimeException()
    }

    // 정상반환
    fun getStringNumber() : String = "1000"
}

 

예시:

기본적인 try ~ catch를 사용했을 경우 의 코드 ( 오래전.. )

internal class RunCatchingService {

    private val log = KotlinLogging.logger { }

    // throw
    fun getAsis() : Int {
        val textNumber = TextNumber()
        try {
            return textNumber.getThrow().toInt()
        }catch (e: RuntimeException){
            log.error { "$e" }
            throw RuntimeException()
        }
    }
.....

위에 코드가 보기에 안좋은지는 모르겠지만 여튼 try ~ catch 로 감싸는 예제를 만들어야 한다면 저런 형태가 될 듯.

 

runCatching을 사용해 보자 0B

internal class RunCatchingService {

    private val log = KotlinLogging.logger { }

    .....

    // throw
    fun get0B() : Int {
        val textNumber = TextNumber()
        return runCatching {
            textNumber.getThrow()
        }.map {
            it.toInt()
        }.getOrThrow()

    }
    .....

try ~ catch 없이 runCatching내에서 실행이 이루어지고 .map으로 다시 Int Type으로 변경 후 반환한다.

( xxxx.map {} 은 보여주기 위함. runCatching내에서 이루어져도 무관 )

실행해보자

Test : 

internal class RunCatchingTest() : StringSpec() {

    private val log = KotlinLogging.logger { }

    init {
....

        "runCatching 0B RuntimeException 발생 그대로 throw" {
            val sut = RunCatchingService()
            shouldThrow<RuntimeException> {
                sut.get0B()
            }
        }
....

RuntimeException이 그대로 반환된다.

 

 

근데 어떤 오류던간에 그냥 NumberFormatException 를 throw 하고 싶은 마음의 변화가 생겼다.

....
    fun get1B() : Int {
        val textNumber = TextNumber()
        return runCatching {
            textNumber.getThrow()
        }.map {
            it.toInt()
        }.onFailure {
            throw NumberFormatException()
        }.getOrThrow()

    }
....

runCatching구문내 예외가 있을 경우 onFailure가 실행되니 여기서 NumberFormatException()으로 throw 처리 한다.

Test:

....
    "runCatching 1B RuntimeException 발생을 NumberFormatException으로 onFailure에서 변경. getOrThrow" {
        val sut = RunCatchingService()
        shouldThrow<NumberFormatException> {
            sut.get1B()
        }
    }
....

 

 

이제 정상적으로 처리해보자.

....
    fun get2B() : Int {
        val textNumber = TextNumber()
        return runCatching {
            textNumber.getStringNumber()
        }.map {
            it.toInt()
        }.onFailure {
            throw NumberFormatException()
        }.getOrThrow()

    }
....

Test:

....
        "runCatching 2B 정상적으로 1000 반환후 타입변환" {
            val sut = RunCatchingService()
            val num = sut.get2B()
            num shouldBe 1000
        }
....

 

대충 확인용으로 보는 코드.

https://github.com/KimHyeongi/KotlinSpringboot-Tips/blob/main/domain-service/src/test/kotlin/com/tistory/eclipse4j/domain/study/RunCatchingTest.kt

 

GitHub - KimHyeongi/KotlinSpringboot-Tips: KotlinSpringboot-Tips

KotlinSpringboot-Tips. Contribute to KimHyeongi/KotlinSpringboot-Tips development by creating an account on GitHub.

github.com

 

 

 

 

 

Kotlin : 

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/run-catching.html

 

runCatching - Kotlin Programming Language

 

kotlinlang.org