JUnit 5에서 Fail 메서드의 유형을 암시적으로 추론

David Mbochi Njonge 2023년6월20일
  1. Kotlin 프로젝트 생성 및 종속성 추가
  2. 유형 변수 V를 추론하기 위한 정보가 충분하지 않음
  3. fail() 메서드의 유형을 명시적으로 유추
  4. 람다 식과 함께 fail() 메서드 사용
  5. fail() 메서드의 유형을 암시적으로 추론
  6. 결론
JUnit 5에서 Fail 메서드의 유형을 암시적으로 추론

테스트는 개발 단계 초기에 버그를 감지하고 애플리케이션의 성능을 개선하며 개발 비용을 줄이는 데 도움이 되므로 모든 애플리케이션 개발에서 중요한 단계입니다.

테스트가 응용 프로그램에서 중요한 프로세스라고 가정합니다. 이 경우 실패한 테스트로 기능 구현을 시작한 다음 최종적으로 테스트를 통과하는 실제 코드를 구현하는 TDD(테스트 주도 개발) 접근 방식을 사용하는 것이 좋습니다.

단위 테스트, 통합 테스트, 기능 테스트 등을 포함하여 다양한 유형의 테스트를 애플리케이션에서 수행할 수 있습니다. 이 튜토리얼에서는 JUnit 5의 단위 테스트 단계에서 사용되는 fail() 메소드의 유형을 암묵적으로 유추하는 방법을 설명합니다.

Kotlin 프로젝트 생성 및 종속성 추가

IntelliJ 개발 환경을 열고 파일 > 새로 만들기 > 프로젝트를 선택합니다. 열리는 창에서 프로젝트 Namekotlin-testing으로 입력하고 Language 섹션에서 Kotlin을 선택한 다음 Build system 섹션에서 Gradle을 선택합니다.

만들기 버튼을 눌러 프로젝트를 생성합니다.

build.gradle 파일을 열고 아래와 같이 junit-jupiter-api 종속성이 있는지 확인합니다. 이 종속성은 코드를 테스트하는 데 사용하는 API를 제공합니다.

dependencies {
    testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2")
    testImplementation 'org.jetbrains.kotlin:kotlin-test'
}

src/main/kotlin 폴더 아래에 Main.kt 파일을 만들고 다음 코드를 복사하여 파일에 붙여넣습니다.

class Student(
    var id: Int,
    var studentName: String?,
    var studentIDCard: String?){

    override fun toString(): String {
        return "student name: $studentName, ID card: $studentIDCard"
    }
}

fun getStudents(): List<Student>{
    return listOf(
        Student(1,"john doe","CSO12022"),
        Student(2,"mary public","CS022022"),
        Student(3,"elon mask","S032022")
    );
}

위의 코드에서 student 개체를 포함하는 목록을 만들었고 이 목록을 사용하여 테스트를 수행합니다.

유형 변수 V를 추론하기 위한 정보가 충분하지 않음

src/test/kotlin 폴더 아래에 Main.kt 파일을 만들고 다음 코드를 복사하여 파일에 붙여넣습니다.

import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.fail

class TestStudents{
    private val students: List<Student> = getStudents();

     @Test
    fun checkEmptyClass(){
        if (students.isNotEmpty()){
            fail("The class is not empty")
        }
    }

}

이 코드에서는 비어 있는지 확인하기 위해 이전 섹션에서 만든 목록을 사용하는 checkEmptyClass()라는 이름의 테스트를 만들었습니다. 목록이 비어 있지 않으면 fail() 메서드를 호출하고 메서드의 인수로 오류 메시지를 전달합니다.

Assertions 클래스의 정적 메서드 fail()을 사용합니다. 클래스의 정규화된 이름은 org.junit.jupiter.api.Assertions입니다.

이 클래스에서 fail() 메소드를 사용할 때 메소드가 일반적이고 유형 매개변수를 제공하지 않았기 때문에 컴파일러는 유형 변수 V를 유추할 정보가 충분하지 않음이라는 메시지와 함께 경고를 표시합니다.

fail() 메서드의 유형을 명시적으로 유추

가장 먼저 떠오르는 가장 쉬운 방법은 다음 코드와 같이 컴파일러를 달래기 위해 형식 매개 변수를 명시적으로 제공하는 것입니다.

import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.fail

class TestStudents{
    private val students: List<Student> = getStudents();

      @Test
    fun checkEmptyClass(){
        if (students.isNotEmpty()){
            fail<String>("The class is not empty")
        }
    }

}

우리가 컴파일러를 달래기 위해 이 명령문을 사용한 이유는 반환 명령문에 도달하기 전에 org.opentest4j.AssertionFailedError 예외가 발생하기 때문에 유형이 반환되지 않기 때문입니다.

간단히 말해서 코드에서 쓸모없는 일반 매개변수를 제공합니다. 다음 섹션에서는 일반 매개변수를 명시적으로 제공하지 않고 이 메서드를 호출하는 방법을 보여줍니다.

이 테스트를 실행하고 다음 메시지와 함께 실패하는지 확인합니다.

The class is not empty
org.opentest4j.AssertionFailedError: The class is not empty

람다 식과 함께 fail() 메서드 사용

위의 예시에 주석을 달고 다음 코드를 복사하여 src/test/kotlin 폴더 아래 Main.kt 파일에 붙여넣습니다.

import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.fail

class TestStudents{
    private val students: List<Student> = getStudents();

    @Test
    fun findInvalidStudentIDCard(){
       students.forEach { student: Student ->
           if (student.studentIDCard?.startsWith("CS") == true){
               println(student)
           }else{
               fail("$student has an invalid id");
           }
       }
    }

}

이 예제에서는 student 목록을 반복하고 유효한 카드 번호로 학생을 기록하고 카드 번호가 유효하지 않은 경우 fail() 메서드를 호출하는 findInvalidStudentIDCard()라는 테스트를 만들었습니다.

우리는 하나의 매개변수를 받아들이고 어떤 값도 반환하지 않는 forEach() 메서드를 사용했습니다. 이를 일반적으로 소비자라고 합니다.

람다 식으로 작업할 때 컴파일러가 메서드에 전달된 Consumer에서 유형을 유추할 수 있으므로 유형을 명시적으로 유추할 필요가 없습니다.

이 코드에서 컴파일러는 컴파일 시간 오류를 표시하지 않습니다. 이 테스트를 실행하고 출력이 아래와 같은지 확인하십시오.

student name: john doe, ID card: CSO12022
student name: mary public, ID card: CS022022

student name: elon mask, ID card: S032022 has an invalid id
org.opentest4j.AssertionFailedError: student name: elon mask, ID card: S032022 has an invalid id

fail() 메서드의 유형을 암시적으로 추론

위의 예시에 주석을 달고 다음 코드를 복사하여 src/test/kotlin 폴더 아래 Main.kt 파일에 붙여넣습니다.

import org.junit.jupiter.api.Test
import org.junit.jupiter.api.fail

class TestStudents{
    private val students: List<Student> = getStudents();

    @Test
    fun checkClassSize(){
        if (students.count() < 5){
            fail("The class is not full")
        }
    }

}

이 예제에서는 목록에 있는 학생 개체의 수를 세는 checkClassSize()라는 테스트를 만들었고, 그 수가 5보다 작으면 fail() 메서드를 호출하고 오류를 전달합니다. 메시지를 메서드의 인수로 사용합니다.

이 예제의 fail() 메서드는 Assertions 클래스의 일반 메서드가 아닙니다. 이 예제의 fail() 메서드는 제네릭이 아닌 org.junit.jupiter.api 패키지에서 가져옵니다.

메서드가 제네릭이 아니므로 매개 변수를 전달할 필요가 없습니다. 이 테스트를 실행하고 출력이 아래와 같은지 확인하십시오.

The class is not full
org.opentest4j.AssertionFailedError: The class is not full

결론

이 튜토리얼에서는 fail() 메서드를 사용할 때 컴파일 시간 오류의 원인을 배웠습니다. 이 경고를 피하기 위해 메소드의 유형을 명시적으로 유추하는 방법을 배웠습니다.

지난 두 섹션에서는 람다 식을 사용할 때 유형이 암시적으로 유추되는 방법과 제네릭이 아닌 메서드를 사용하여 유형 유추를 피하는 방법을 배웠습니다.

David Mbochi Njonge avatar David Mbochi Njonge avatar

David is a back end developer with a major in computer science. He loves to solve problems using technology, learning new things, and making new friends. David is currently a technical writer who enjoys making hard concepts easier for other developers to understand and his work has been published on multiple sites.

LinkedIn GitHub