자바 개발자가 가장 많이 사용하는 테스트 프레임워크이다.
단위테스트를 작성하는 자바 개발자의 93%가 JUnit을 사용중이고, 자바 8 이상을 필요로 한다.
테스트들이 실행되기 전 / 후로 1번 실행되는 어노테이션
각각의 테스트들이 실행되기 전 / 후로 1번씩 실행되는 어노테이션
해당 테스트를 제외하고 싶을때 사용하는 어노테이션
테스트 설명을 작성할 때 사용하는 어노테이션
(expected, actual)
실제 값이 기대한 값과 같은지 확인
assertEquals(StudyStatus.DRAFT, study.getStatus(),
() -> "스터디를 처음 만들면 " + StudyStatus.DRAFT + " 상태다.");
// 메시지를 람다식으로 표현하는 이유는 람다식으로 표현하면 테스트가 실패했을 시에만 메시지 연산을 하기 때문
// Supplier<String> 타입의 인스턴스를 람다 형태로 제공
(actual)
값이 null이 아닌지 확인
assertNotNull(study);
(boolean)
다음 조건이 참(true)인지 확인
assertTrue(study.getLimit() > 0,
() -> "스터디 최대 참석 가능 인원은 0보다 커야한다");
(executables...)
모든 확인 구문 확인
테스트가 실패해도 다음구문까지 모두 확인하고 싶을 때
assertAll(
() -> assertNotNull(study),
() -> assertEquals(StudyStatus.DRAFT, study.getStatus(),
() -> "스터디를 처음 만들면 " + StudyStatus.DRAFT + " 상태다."),
() -> assertTrue(study.getLimit() > 0,
() -> "스터디 최대 참석 가능 인원은 0보다 커야한다")
);
(expectedType, executable)
예외 발생 확인
public class Study {
private int limit;
public Study(int limit) {
if (limit < 0)
throw new IllegalArgumentException("limit은 0보다 커야합니다.");
this.limit = limit;
}
}
IllegalArgumentException exception =
assertThrows(IllegalArgumentException.class, () -> new Study(-10));
assertEquals("limit은 0보다 커야합니다.", exception.getMessage());
(duration, executable)
특정 시간 안에 실행이 완료되는지 확인
// timeout 성공 케이스
assertTimeout(Duration.ofMillis(100), () -> new Study(10));
// timeout 실패 케이스
assertTimeout(Duration.ofMillis(100), () -> {
new Study(10);
Thread.sleep(300);
});
// 시간안에 성공못하면 기다리지 않고 그대로 테스트종료
// 사용시 주의! (예상치 못한 트랜잭션 문제 발생 가능)
assertTimeoutPreemptively();
@RepeatedTest(value = 10, name = "{displayName} -> {currentRepetition}/{totalRepetitions}")
@DisplayName("반복 테스트")
// name 안써도 깔끔하게 나온다. 굳이 안써도 ㅎㅎ;
@ParameterizedTest
@ValueSource(strings = {"새벽에", "치킨이", "땡기는데", "시킬까?"})
@DisplayName("다른 파라미터로 반복 테스트")
void parameterizedTest(String parameter) {
System.out.println(parameter);
}
인자들을 객체로 받는것도 가능하다.
@ParameterizedTest
@CsvSource({"10, '자바 테스트'", "20, 스프링"})
@DisplayName("여러 인자 반복 테스트")
void parametersTest(ArgumentsAccessor argumentsAccessor) {
Study study = new Study(argumentsAccessor.getInteger(0), argumentsAccessor.getString(1));
System.out.println(study);
}
기본적으로 JUnit에선 테스트들이 각각의 인스턴스를 가지고 실행된다.
또한 순서도 보장하지 않는다.
유닛테스트는 서로 의존하지 않고 독립적으로 실행이 되어야 하기 때문인데,
시나리오 테스트를 해야할 경우, 예를들어 회원이 로그인을 하고 -> 게시판을 가서 -> 글을 작성하고 -> 저장한다.
이런식으로 테스트를 해야할 경우도 생긴다
테스트들이 같은 인스턴스 안에서 실행하게 해주는 어노테이션
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class JavaTest {}
테스트간의 순서를 지정해주는 어노테이션
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class JavaTest {
@Order(1)
@DisplayName("로그인")
void login() {}
@Order(2)
@DisplayName("글 작성")
void write() {}
}