@Test
테스트 메소드를 나타내는 어노테이션으로, 테스트하고자 하는 메서드에 필수로 작성되어야한다.
public class JunitJupiterTests {
@Test
void stringTest() {
assertThat(StringUtils.hasText("")).isFalse();
}
}
@Test
메서드는 정적 테스트 케이스로, 컴파일 시간에 모든 내용이 결정된다.
실행 시간 동안에는 TC의 동작을 변경할 수 없다.
Assumption
메서드를 활용해 동적인 동작을 추가할 수 있으나 제한된 부분이 있다.
@RepeatedTest
repetition + {currentRepetition} + of + {totalRepetitions}
ex) repetition 1 of 5
반복 수 지정시, 각각 반복되는 테스트에 대한 display name을 지정할 수 있으며, 이때 정적 placeholder를 사용해 패턴을 만들 수도 있다.
{displayName}
: @RepeatedTest
메서드의 Display Name
{currentRepetition}
: 현재 반복 횟수
{totalRepetitions}
: 반복활 총 횟수
[Resolver](./junit5#Dependency Injection)를 이용해 RepetitionInfo
, TestInfo
타입의 인자를 받을 수 있다.
public class RepeatedMethodTest {
@RepeatedTest(5)
void repetition_test(TestInfo testInfo, RepetitionInfo repetitionInfo) {
assertThat(testInfo.getDisplayName()).isEqualTo("repetition " + repetitionInfo.getCurrentRepetition() + " of " + repetitionInfo.getTotalRepetitions());
assertThat(repetitionInfo.getTotalRepetitions()).isEqualTo(5);
}
@RepeatedTest(value = 5, name = "{displayName} {currentRepetition}/{totalRepetitions}")
void repetition_name_test(RepetitionInfo repetitionInfo) {
assertThat(repetitionInfo.getTotalRepetitions()).isEqualTo(5);
}
}
@ParameterizedTest
파라미터화 테스트는 각각 다른 인자로 테스트를 반복적으로 실행할 수 있게 해주는 어노테이션이다.
ARGUMENTS_WITH_NAMES_PLACEHOLDER
기본값 "[" + INDEX_PLACEHOLDER + "] " + ARGUMENTS_WITH_NAMES_PLACEHOLDER
@ParameterizedTest
는 단독으로 사용 못하며, 추가적으로 호출 시 사용될 인자도 최소 1개 적어줘야한다.
placeholder
the complete, comma-separated arguments list
the complete, comma-separated arguments list with parameter names
또한 @ParamterizedTest
를 사용할 때는 항상 인자를 받는 파라미터가 먼저 와야한다.
# 올바른 예
@ParameterizedTest
@ValueSource(strings = "test")
void testWithRegularParameterResolver(String str, TestReporter testReporter) {
testReporter.publishEntry("argument", str);
}
# 잘못된 예
@ParameterizedTest
@ValueSource(strings = "test")
void testWithRegularParameterResolver(TestReporter testReporter, String str) {
testReporter.publishEntry("argument", str);
}
@ValueSource
다양한 타입의 인자를 배열로 받아서 사용할 수 있게 해주는 어노테이션 하나의 인자만 받는 파라미터화 테스트에만 적용 가능하다.
지원하는 타입: short
, byte
, int
, long
, float
, double
, char
, boolean
, java.lang.String
public class ParameterizedMethodTest {
@ParameterizedTest
@ValueSource(strings = {"faker", "zeus", "oner", "keria", "gumayusi"})
void parameterized_test(String t1) {
assertThat(StringUtils.hasText(t1));
}
}
Null and 빈 값 테스트
잘못된 입력이 들어올 수 있는 경우에 대한 테스트를 할수도 있다.
@ParameterizedTest 메소드에 null을 제공
primitive type (int, long 등)에는 사용할 수 없음.
@NullSource 와 @EmptySource 기능들을 합친 어노테이션
@EnumSource
Enum에 정의된 상수 테스트를 가능하게 해주는 어노테이션이다.
org.junit.jupiter.params.provider.NullEnum
검색 조건 (문자열, 정규식) mode에서 사용됌
EnumSource.Mode.INCLUDE, EnumSource.Mode.EXCLUDE, EnumSource.Mode.MATCH_ALL, EnumSource.Mode.MATCH_ANY, names
@ParameterizedTest
@EnumSource
void MonthEnumTest(Month month) {
assertThat(month).isNotNull();
}
@ParameterizedTest
@EnumSource(names = {"MAY", "JUNE"})
void enumSourceIncludeModeTest(Month month) {
assertThat(EnumSet.of(Month.JUNE, Month.MAY)).contains(month);
}
@ParameterizedTest
@EnumSource(mode = EnumSource.Mode.EXCLUDE, names = {"MAY", "JUNE"})
void enumSourceExcludeModeTest(Month month) {
assertThat(EnumSet.of(Month.JUNE, Month.MAY)).doesNotContain(month);
}
@ParameterizedTest
@EnumSource(mode = EnumSource.Mode.MATCH_ANY, names = {"^.*SDAY$","^.*ESDAY$"})
void enumSourceMatchAnyModeTest(DayOfWeek day) {
assertThat(EnumSet.of(DayOfWeek.THURSDAY, DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY)).contains(day);
}
@ParameterizedTest
@EnumSource(mode = EnumSource.Mode.MATCH_ALL, names = {"^.*SDAY$","^.*ESDAY$"})
void enumSourceMatchAllModeTest(DayOfWeek day) {
assertThat(EnumSet.of(DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY)).contains(day);
}
@MethodSource
복잡한 인수를 전달할 때 사용하는 방법으로 다음 조건을 지켜야한다.
클래스 단위 생명주기(@TestInstance(Lifecycle.PER_CLASS)
)가 아닌 경우에는 static method여야한다.
각각의 팩터리 메서드는 반드시 Stream
타입을 리턴해야한다.
@ParameterizedTest
@MethodSource
void stringMethodSourceTest(String str) {
assertThat(StringUtils.hasText(str)).isTrue();
}
static Stream<String> stringMethodSourceTest() {
return Stream.of("faker", "bang", "wolf");
}
@ParameterizedTest
@MethodSource("range")
void primitiveTypeMethodSourceTest(int i) {
assertThat(i).isLessThan(20);
}
static IntStream range() {
return IntStream.range(0, 20);
}
default값이 테스트 메소드명이므로 테스트 메소드명과 동일한 경우 생략이 가능하다.
파라미터가 여러개인 경우
테스트 메서드 파라미터가 여러개인 경우일 때는 Arguements
를 사용해 반환해주면된다.
@ParameterizedTest
@MethodSource("stringAndIntProvider")
void multiParameterMethodSourceTest(String name, int age) {
assertThat(name).isNotBlank();
assertThat(age).isEqualTo(26);
}
static Stream<Arguments> stringAndIntProvider() {
return Stream.of(
Arguments.arguments("faker", "26"),
Arguments.arguments("bang", "26")
);
}
외부 정적 팩토리 메서드를 사용하는 경우
package dh0023.example.springbatchreal.junit5.testmethod;
import org.junit.jupiter.params.provider.Arguments;
import java.util.stream.Stream;
public class T1 {
static Stream<Arguments> members() {
return Stream.of(
Arguments.arguments("faker", "26", "mid"),
Arguments.arguments("bang", "26", "bottom"),
Arguments.arguments("wolf", "26", "support")
);
}
}
@ParameterizedTest
@MethodSource("dh0023.example.springbatchreal.junit5.testmethod.T1#members")
void externalMethodSourceTest(String name, int age, String position) {
assertThat(name).isNotBlank();
assertThat(position).isNotBlank();
assertThat(age).isEqualTo(26);
}
@ArgumentsSource
커스텀 또는 재사용가능한 ArgumentsProvider
를 지정해줄 때 사용한다. ArguementsProvider
는 반드시 클래스 탑 레벨에 선언하거나, 정적 중첩 클래스로 선언해야한다.
@ParameterizedTest
@ArgumentsSource(value = MyArgumentsProvider.class)
void argumentSourceTest(String fruit) {
assertThat(fruit).isNotBlank();
}
static class MyArgumentsProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return Stream.of("apple", "banana").map(Arguments::of);
}
}
참고