JUnit을 사용해서 테스트를 진행하면 매개변수를 사용할 수가 없다.
그런데 도메인 단위의 테스트를 진행하다 보면 같은 코드에 매개변수만 달리하는 중복된 코드가 발생하는 경우가 종종 있다.
이럴 경우 JUnitParams 를 사용하면 매개변수를 이용할 수 있어서 테스트 코드가 훨씬 간결해진다.
사용법은 JUnit4와 JUnit5에 따라 다르다.
1. JUnit4
다음과 같이 의존성을 추가한다.
Maven
<dependency>
<groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId>
<version>1.1.1</version>
<scope>test</scope>
</dependency>
Gradle
testCompile 'pl.pragmatists:JUnitParams:1.1.1'
다음과 같이 테스트 코드를 작성하면 된다.
@RunWith(JUnitParamsRunner.class)
public class PersonTest {
@Test
@Parameters({"17, false",
"0, true" })
void testFree(int basePrice, boolean isFree) {
Event event = Event.builder()
.basePrice(basePrice)
.build();
assertThat(event.isFree()).isEqualsTo(isFree);
}
//위의 경우엔 파라미터가 타입세이프하지 않으므로 다음과 같이 작성하는 편이 훨씬 좋은 코드
@Test
@Parameters(method = "parametersForTestFreeSafe")
void testFreeTypeSafe(int basePrice, boolean isFree) {
Event event = Event.builder()
.basePrice(basePrice)
.build();
assertThat(event.isFree()).isEqualsTo(isFree);
}
private Object[] parametersForTestFreeSafe() {
return new Object[] {
new Object[] {17, false},
new Object[] {0, true}
};
}
}
# 참고로 위에서 testFreeTypeSafe메서드가 참조하는 private Object[] parametersForTestFreeSafe() 메서드에서
하일라이트된 parametersFor 가 JUnitParams에서 제공하는 편의기능 prefix로 이후 나오는 메서드명을 유추하여 실행하도록 한다.
예를 들어 parametersForTestFreeSafe의 경우, 편의기능 prefix인 parametersFor 를 제외한 메서드명인 testFreeSafe() 메서드가 실행될 때 해당 참조 메서드가 실행된다. 따라서 위의 testFreeTypeSafe의 @Parameters 어노테이션에 method 값을 생략해도 된다.
2. JUnit5
다음과 같이 의존성을 추가한다.
Maven
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
Gradle
testCompile 'org.junit.jupiter:junit-jupiter-params:5.9.2'
테스트 코드가 JUnit4와 달라진 점은
- 클래스 레벨의 @RunWith(JUnitParamsRunner.class) 어노테이션 삭제
- 메서드 레벨의 @Test 가 @ParameterizedTest 로 대체
- 메서드 레벨의 @Parameters 가 @CsvSource, @MethodSource 등으로 대체
- @MethodSource의 참조 메서드는 테스트를 진행할 때 이미 메모리에 올라가 있어야 하기 때문에 static으로 선언
테스트 코드 예제는 다음과 같다.
@ParameterizedTest
@CsvSource({
"0, 0, true",
"0, 100, false",
"100, 0, false",
})
public void testFree(int basePrice, int maxPrice, boolean isFree) {
Event event = Event.builder()
.basePrice(basePrice)
.maxPrice(maxPrice)
.build();
event.update();
assertThat(event.isFree()).isEqualTo(isFree);
}
@ParameterizedTest
@MethodSource("isOffline")
public void testOffline(String location, boolean isOffline) {
Event event = Event.builder()
.location(location)
.build();
event.update();
assertThat(event.isOffline()).isEqualTo(isOffline);
}
private static Stream<Arguments> isOffline() {
return Stream.of(
Arguments.of("강남역", true),
Arguments.of(null, false),
Arguments.of("", false)
);
}
https://github.com/Pragmatists/JUnitParams