자바를 테스트하기 위한 Framework이다. 이 포스트를 작성하는 현재 JUnit의 최신버전은 5버전이다.
JUnit5는 아래의 3개의 모듈로 구성되어있다.
JUnit Platform : JUnit의 핵심 모듈로서 테스트 프레임워크를 구동하기 위한 런처와 테스트 엔진을 위한 API를 제공.
JUnit Jupiter : JUnit5를 위한 테스트 API와 실행 엔진을 제공.
JUnit Vintage : 이전 버전의 JUnit으로 작성된 테스트를 JUnit5에서 실행하기 위한 모듈 제공.
스프링부트에서의 의존성 주입
dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
스프링 이외의 환경에서의 의존성 주입
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter-api:5.9.3') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
JUnit3 또는 JUnit4 로 작성된 코드가 있을경우 exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
부분은 제거한다.
JUnit은 기본적으로 @Test 어노테이션이 붙은 메소드마다 하나의 인스턴스로 생성되어 테스트가 실행된다. 그러므로 테스트가 서로 영향을 미치지 않게 되어있다. 하지만 테스트코드를 만들다보면 다른 테스트의 결과를 기반으로 테스트를 진행할 필요가 있는 경우가 있다. 예를 들어 아래와 같은 경우이다.
위의 4가지를 테스트 할 때마다 매번 새로운 데이터를 등록하는것은 번거로운 일이 될 것이다.
이 때 테스트 인스턴스의 범위를 수정하여 각 테스트가 서로 영향을 주도록 변경할 수 있다.
@TestInstance 어노테이션을 Test Class에 지정함으로서 테스트의 라이프 사이클을 조정가능하다.
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
위와 같이 LifeCycle.PER_CLASS로 @TestInstance를 설정해 주게 되면 @Test 어노테이션이 붙은 메소드마다 생성되던 인스턴스가 각각의 테스트 클래스별로 생성되게 된다. 그러므로 클래스마다 테스트중에 변경된 사항을 서로 공유가 가능하다.
테스트 인스턴스를 통해서 각각의 테스트가 서로 영향을 줄 수 있도록 지정하는 방법을 알아보았다. 그런데 각 테스트는 서로 실행되는 순서를 보장하지 않는다. 그러므로 테스트가 등록 > 조회 > 수정 > 삭제
순으로 실행된다는 보장이 없다. 이 때 이 순서를 지정하는 방법은 아래와 같다.
아래의 코드와 같이 @Order를 통해서 테스트의 순서를 지정할 수 있다. @Order 에 설정된 값이 작을수록 우선순위가 높으며 파라미터는 int이기 때문에 음수도 가능하다.
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class ServiceTest {
@Order(1)
@Test
void test1() {
System.out.println(1);
}
@Order(2)
@Test
void test2() {
System.out.println(2);
}
@Order(3)
@Test
void test3() {
System.out.println(3);
}
@Order(4)
@Test
void test4() {
System.out.println(4);
}
}
정해진 횟수만큼의 테스트를 반복한다. RepetitionInfo 객체를 통해 반복횟수에 대한 정보를 가져올 수 있다.
@RepeatedTest(3)
void insert(RepetitionInfo info) {
System.out.println(info.getCurrentRepetition() + "/" + info.getTotalRepetitions());
}
하나의 테스트에 다른 파라미터를 넘기면서 여러번 테스트를 진행할 수 있도록 해주는 기능이다.
@MethodSource, @ArgumentSource, @CvsSource, @ValueSource, @NullSource, @EmptySource 등등의 기능을 통해서 다양한 방식으로 파라미터를 전달하여 사용할 수 있다.
여기서는 @MethodSource를 이용해서 파라미터를 넘기는 방법을 예제로 작성했다.
@ParameterizedTest
@MethodSource("fixtureForTest1")
void test1(String name, int index, String expected) {
String actual = name + index;
Assertions.assertEquals(actual, value);
}
static List<Arguments> fixtureForTest1() {
return List.of(
Arguments.arguments("테스트", 0, "테스트0"),
Arguments.arguments("테스트", 1, "테스트1"),
Arguments.arguments("테스트", 2, "테스트2"),
Arguments.arguments("테스트", 3, "테스트3")
);
}
assertj 의 Assumptions를 이용해서 테스트 조건을 지정할 수 있다. 아래와 같이 테스트코드에 입력하게 되면 참/거짓 결과에 따라서 하위의 테스트코드를 실행할지 결정된다.
Ex) Assumptions.assumeThat("실제값").isEqualTo("기대값")
@EnabledOnJre, @EnabledOnOs, @EnabledIf, @EnabledIfSystemProperty 등 @Enabled로 시작하는 어노테이션들이 있다. 각 필요에 따라 @Test 메소드위에 조건과 함께 설정해서 사용할 수 있다.