JUnit이란?
자바 언어를 사용하는 테스트 프레임워크중 하나로, 주로 단위 테스트를 작성하고 실행하는 데에 사용된다.
@Test
해당 메서드가 테스트 메서드임을 나타낸다.
return 타입이 void가 아니라면, 해당 메서드는 테스트 메서드가 아니다.
@DisplayName
해당 테스트의 이름을 나타낸다. 테스트의 이름을 한글로 작성하고 싶다면 @DisplayName 애노테이션을 사용하는 것이 좋다.
@Nested
해당 클래스가 중첩 클래스임을 나타낸다.
중첩 클래스- 클래스 내부에 선언된 클래스를 의미한다. 클래스의 의미를 명확하게 하기 위해서 중첩으로 표현한다.
@Nested 애노테이션을 사용하면 해당 메서드는 중첩 클래스 내부에 있는 것으로 판단한다.
@Disabled
해당 테스트를 비활성화한다. @Disabled 애노테이션은 @Test 애노테이션과 함께 사용된다.
클래스에도 적용 가능하며 이 경우 해당 클래스의 모든 테스트가 비활성화 된다.
assertEquals
두 값이 같은지 비교한다. 두 값이 같다면 테스트는 성공하며, 두 값이 다르다면 테스트는 실패한다.
'org.junit.jupital.api.Assertions' 클래스에 정의되어 있다. ('static'으로 임포트하여 사용)
'assertEquals' 메서드는 'assertEquals(expected, actual)' 형태로 오버로딩 되어있다.
객체 또한 equals를 호출하기 때문에 아래 테스트 코드는 성공하지 못한다.
void assertEquals_메서드로_두_객체가_같은지_비교한다() {
class LocalObject {
private final int value;
public LocalObject(int value) {
this.value = value;
}
}
final var a = new LocalObject(1);
final var b = new LocalObject(1);
// TODO: LocalObject 클래스의 equals를 재정의하여 아래 코드가 테스트를 성공시키도록 해주세요.
assertEquals(a, b);
}
LocalObject 클래스에 equals 메서드를 정의하여 해결한다.
void assertEquals_메서드로_두_객체가_같은지_비교한다() {
class LocalObject {
private final int value;
public LocalObject(int value) {
this.value = value;
}
public boolean equals(Object o){
if (o instanceof LocalObject){
return this.value==(((LocalObject) o).value);
}
return false;
}
}
final var a = new LocalObject(2);
final var b = new LocalObject(2);
// TODO: LocalObject 클래스의 equals를 재정의하여 아래 코드가 테스트를 성공시키도록 해주세요.
assertEquals(a, b);
}

assertEquals(expected, actual, message)는 테스트가 실패했을 때 출력되는 메시지를 지정할 수 있다.
'message' 는 테스트가 실패했을 때 출력되는 메시지이다.
assertNotEquals
두 값이 다르다면 테스트를 성공시킨다.
assertThrows
특정 예외가 발생하는지 비교한다. 특정 예외가 발생한다면 테스트는 성공하며, 특정 예외가 발생하지 않
assertThrows(expectedType, executable) 형태로 오버로딩 되어있다.
@Test
@DisplayName("assertThrows 메서드로 특정 예외가 발생하는지 비교한다")
void assertThrows_메서드로_특정_예외가_발생하는지_비교한다() {
// TODO: try-catch문을 사용하지 않고 assertThrows 메서드를 사용하여 테스트가 성공하도록 해주세요.
try {
causeException();
} catch (Exception e) {
return;
}
throw new RuntimeException("예외가 발생하지 않았습니다.");
}
위 코드를 assertThrows 메서드가 들어간 코드로 바꾸어보기
@Test
@DisplayName("assertThrows 메서드로 특정 예외가 발생하는지 비교한다")
void assertThrows_메서드로_특정_예외가_발생하는지_비교한다() {
// TODO: try-catch문을 사용하지 않고 assertThrows 메서드를 사용하여 테스트가 성공하도록 해주세요.
/*try {
causeException();
} catch (Exception e) {
return;
}
*/
assertThrows(Exception.class, ()-> causeException());
}
assertDoesNotThrow
특정 예외가 발생하지 않는다면 테스트를 성공시킨다. 메서드를 사용하지 않아도 테스트는 성공하지만, 테스트의 의도를 명확하게 표현할 수 없다.
assertAll
여러 검증 코드를 한 번에 실행한다. 'assertAll(executables)' 형태로 오버로딩 되어있다.
'assertAll'을 사용하는 이유는 여러 검증 코드가 존재할 때 문제가 발생한다면 어떤 검증 코드에서 문제가 발생했는지 알기 어렵기 때문이다.
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을 사용해 모든 테스트의 결과를 한 번에 볼 수 있다.
@ParameterizedTest
테스트에 필요한 파라미터를 제공하는 테스트이다.보통 테스트에 따라 @ValueSource와 @MethodSource 같은 애노테이션 중 적합한 애노테이션을 선택하여 테스트를 진행할 수 있다.ParameterizedTest를 사용하면 하나의 테스트 로직 내에서 여러 변수를 선언하지 않고, 주입받은 값을 활용하여 유연하고 단편화된 테스트 코드를 작성 할 수 있다.
@ParameterizedTest
@ValueSource(ints={1,2,3,4})
@DisplayName("ValueSource 애노테이션을 붙여 정수 매개변수를 여러 번 입력받는다")
void ValueSource_애노테이션을_붙여_정수_매개변수를_여러_번_입력받는다(int value) {
// TODO: `@ValueSource`를 사용하지 않고 여러 정수의 범위를 테스트하는 것과, `@ValueSource`를 사용해서 테스트하는 것의 차이를 비교해보세요.
assertTrue(value>0 && value< 10);
}

@MethodSource
메서드 이름을 인자로 받아들이며, 인자에서 호출된 메서드는 테스트 메서드에 전달될 인자를 반환한다.
@속성으로 사용된 해당 메서드는 'Arguments('ParameterizedTest' 에서 사용되는 값의 하나를 가리킨다)' 를 'Stream'에 담아 return 하여 각각의 Arguments가 테스트에 하나씩 전달 되도록 구현된 형태이다.
@ParameterizedTest
@MethodSource("methodSourcesTestArguments")
@DisplayName("MethodSource 애노테이션을 붙여 Object 매개변수를 여러 번 입력받는다")
void MethodSource_애노테이션을_붙여_Object_매개변수를_여러_번_입력받는다(Object object) { assertInstanceOf(Object.class, object);}
// TODO: `MethodSource`를 사용하지 않고 Object 객체들을 직접 선언하여 테스트하는 방식과, `MethodSource`를 사용하여 Object를 입력받아 테스트하는 방식의 차이를 비교해보세요.
/*Object object1 = new Object();
Object object2 = new Object();
Object object3 = new Object();
Object object4 = new Object();
assertInstanceOf(Object.class, object1);
assertInstanceOf(Object.class, object2);
assertInstanceOf(Object.class, object3);
assertInstanceOf(Object.class, object4);
*/
/**
* `Arguments`를 `Stream` 내부에 여러 개 선언해줌으로서, 각 `Arguments`마다 각각의 테스트를 수행하도록 구현할 수 있습니다.
*/
private static Stream<Arguments> methodSourcesTestArguments() {
return Stream.of(
Arguments.arguments(new Object()),
Arguments.arguments(new Object()),
Arguments.arguments(new Object()),
Arguments.arguments(new Object())
);
}
'study' 카테고리의 다른 글
| [초록스터디] 자바 컬렉션 API, Optional (1) | 2024.07.08 |
|---|