JUnit5와 단위테스트

오젼·2024년 3월 31일
1

JUnit5와 단위테스트

프로그램을 작은 단위들로 쪼개서 해당 기능들이 올바르게 작동하는지 테스트를 하는 것이 단위테스트. 단위테스트를 지원하는 프레임워크 중 유명한 것이 JUnit5.

키워드

@Test

Test 메서드임을 나타내기 위한 어노테이션. 이걸 붙여야만 테스트 메서드로 인식한다.

void

테스트 메서드는 무조건 void 메서드여야 한다.

@Nested

중첩 클래스 내부에 있다는 것을 알리기 위한 어노테이션.

@Disabled

테스트가 실행되지 않는다.

assertEquals(expected, actual), equals()

assertEquals()의 인자로 사용자가 정의한 오브젝트를 넣어주려고 할 때,
equals()가 해당 클래스에 정의되어 있지 않으면 오류가 난다.
따라서 equals()가 해당 클래스에 오버로딩 되어 있어야 한다.

public boolean equals(Object o) {
	if (this == o) return true;
	if (o == null || getClass() != o.getClass()) return false;
	LocalObject that = (LocalObject) o;
	return value == that.value;
}
  1. 서로 아예 같으면 return true
  2. o가 널이거나 클래스의 종류가 다르면 return false -> 이래야 밑에서 LocalObject로 캐스팅한 다음 값을 비교할 수 있음
  3. 해당 클래스로 Object o를 캐스팅 하고 변수 값을 비교함

이거 그냥 인텔리제이에서 자동으로 생성해주는 거였다. cmd+n 누르고 equals() and hashCode() 누르면 됨

챗지피티에선

// 주어진 객체가 MyClass의 인스턴스인지 확인
if (!(obj instanceof MyClass)) {
	return false;
}

를 사용하라고 했었는데
instanceOf는 컴파일 시점에 작동하고 getClass()는 런타임 시점에 작동함. 따라서 정적으로 클래스가 결정된 경우에나 instanceOf을 사용할 수 있는 거고, 동적으로 결정되는 경우에는 getClass()로 비교를 해주어야 함.

assertNotEquals(unexpected, actual)

두 값이 다르다면 테스트를 성공시킨다.

assertSame(expected, actual)

두 객체가 같으면 테스트를 성공시킨다.

assertThrows(expectedType, executable)

assertThrows(Exception.class, this::causeException);

이런식으로 사용
아니면 람다식으로 사용할 수도 있음

assertThrows(ArithmeticException.class, () -> {
	int result = 10 / 0; // 0으로 나누는 연산을 수행하면 ArithmeticException이 발생함
});

assertDoesNotThrow(executable)

assertDoesNotThrow(() -> {
	final var number = Integer.valueOf(0x80000000);
});

assertAll(executables)

assertAll(
	() -> assertEquals(3, 1 + 2),
	() -> assertEquals(5, 3 + 2),
	() -> assertEquals(21, 7 * 3),
	() -> assertEquals(32, 3 * 7 ^ 5),
	() -> assertEquals(4, 7 * 3 / 5 + 33 / 21),
	() -> assertEquals(22, 33 * 3 / 5 + 7 / 2),
	() -> assertEquals(22, 33 * 3 / 5 + 7 / 2 + 1)
);

assertAll()을 사용하지 않으면 차례대로 코드가 진행되다가 throw가 되면 거기서 멈춘다. 하지만 사용하면 끝까지 진행하고 몇 개의 실패가 있었는지 Multiple Failures로 알려준다.

@ParameterizedTest

인자를 제공하는 테스트.
보통 테스트에 따라 @ValueSource@MethodSource 같은 어노테이션 중 적합한 어노테이션을 선택하여 테스트를 진행할 수 있다.

@ValueSource

public class MyTest {

    @ParameterizedTest
    @ValueSource(strings = {"apple", "banana", "orange"})
    public void testStringNotEmpty(String value) {
        assertTrue(value.length() > 0);
    }
}

한 메서드를 가지고 여러 테스트를 진행해보고 싶을 때 @ValueSource를 사용해서 매개변수를 간단하게 지정해줄 수 있다. ints, strings, doubles, classes 등을 사용할 수 있다.
이는 함수의 인자에 하나씩 들어가서 실행되게 된다.
이 때 ValueSource의 타입과 함수 인자의 타입이 다르면 자동 형변환이 일어나게 된다.

@MethodSource

이건 단순한 변수가 아니라 메서드를 전달해주고 싶을 때.

public class ExampleTest {

    @ParameterizedTest
    @MethodSource("provideArguments")
    void testWithArguments(int expected, int input) {
        assertEquals(expected, input * input);
    }

    static Stream<Arguments> provideArguments() {
        return Stream.of(
                Arguments.arguments(4, 2),
                Arguments.arguments(9, 3),
                Arguments.arguments(16, 4)
        );
    }
}

0개의 댓글