오늘은 junit5의 기본적인 사용법만 살펴보자. 예전에 릴리즈 되기 전에
여기에 대충 사용법만 포스팅한적이 있었다. 아주 junit5 의 기본적인 내용만 살펴봤으니 좀 더 많은 내용은 문서를 통해서 확인하면 더 좋을 듯 싶다. 많이 바뀐 내용은 없는 듯 하니 추가할 내용은 없을 것 같다. 기본적으로 class가
public
이 아니여도 되고, test 메서드도
public
이 아니고
package private
이여도 된다는 것은 동일하다. 아주아주 기본적인 사용법은 예전에 살펴본 내용이므로 생략하자. 그렇게 어려운 내용은 아니니 한번씩 해보면 좋을 것 같다.
ExtendWith
Junit5 에 추가된 어노테이션중에 하나이다. 어노테이션명 그대로
ExtendWith
은 뭔가를 확장 시킬 수 있는 그런 어노테이션이다. 실제로 코드는 아래와 같다.
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Repeatable(Extensions.class)
@API(status = STABLE, since = "5.0")
public @interface ExtendWith {
Class<? extends Extension>[] value();
}
별 다른 내용은 없고 value에는 Extension를 상속한 클래스만 가능하다. 실제로
Extension
인터페이스는 딱히 구현할 것도 없는 마커 인터페이스 이다.
Extension
를 사용하는 인터페이스도 많으니 한번씩 살펴보도록 하고 오늘할 내용은
ParameterResolver
라는 인터페이스를 사용하는법을 알아보도록 하자.
ParameterResolver
인터페이스는 파라미터를 컨트롤 할 수 있는 그런 인터페이스이다. 실제로 junit4에서는 무조건 기본생성자가 있어야 하며
test
메서드는 파라미터가 없어야 했었다. 하지만 junit5 부터는 기본생성자뿐만 아니라
test
메서드에도 파라미터가 있어도 된다. 하지만 그 타입에 맞게 구현은 해줘야 한다. 그게 바로
ParameterResolver
인터페이스이다.
public interface ParameterResolver extends Extension {
boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
throws ParameterResolutionException;
Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
throws ParameterResolutionException;
}
ParameterResolver
인터페이스는 다음과 같은 형태이다.
supportsParameter
지원가능한 파라미터 타입을 검사하고
resolveParameter
메서드는 실제 지원가능한 타입을 조작하는 그런 메서드라고 생각하면 된다. 뭔가 spring과 비슷하다. 약간 비슷할 수 밖에 없는게 junit5 를 개발한 개발자가 spring 팀에도 속해있기 때문이다. 그래서 비슷한 구석이 있을 수 있다.
한번 아주간단하게 구현을 해보자.
class UserInfoParameterResolver implements ParameterResolver {
@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return (parameterContext.getParameter().getType() == UserInfo.class);
}
@Override
public UserInfo resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return new UserInfo("wonwoo", "wonwoo@test.com");
}
}
ParameterResolver
를 구현한 구현체이다. 간단하게 어떤 동작을 하는지 보는 것이기 때문에 의미 있는 코드는 아니니 참고하기 바란다.
class UserInfo {
private final String name;
private final String email;
UserInfo(String name, String email) {
this.name = name;
this.email = email;
}
public String getEmail() {
return email;
}
public String getName() {
return name;
}
}
다음은 UserInfo를 담는 Object이다. 간단하므로 자세한 내용은 생략한다. 어떻게 사용하는지 한번 살펴보자.
@ExtendWith(UserInfoParameterResolver.class)
class NestedUserInfoTest {
private final UserInfo userInfo;
NestedUserInfoTest(UserInfo userInfo) {
this.userInfo = userInfo;
}
@Test
void user_info_test() {
assertEquals(userInfo.getName(), "wonwoo");
assertEquals(userInfo.getEmail(), "wonwoo@test.com");
}
}
위와 같이 기본 생성자가 없어도 테스트는 통과 한다. 아래와 같이 test 메서드에 파라미터로 UserInfo 타입을 받아도 동일한 결과를 얻을 수 있다.
@ExtendWith(UserInfoParameterResolver.class)
class UserInfoTest {
@Test
void user_info_test(UserInfo userInfo) {
assertEquals(userInfo.getName(), "wonwoo");
assertEquals(userInfo.getEmail(), "wonwoo@test.com");
}
}
또한 spring과 비슷하다고 느낀점이 메타 어노테이션도 지원한다. 아래와 같이 특정한 어노테이션을 만든 후에
ExtendWith
를 사용해도 된다.
@ExtendWith(UserInfoParameterResolver.class)
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface UserInfoExtension {
}
위와 같이 메타 어노테이션을 만들었다면 다음과 같이도 테스트를 할 수 있다.
@UserInfoExtension
class UserInfoTest {
@Test
void user_info_test(UserInfo userInfo) {
assertEquals(userInfo.getName(), "wonwoo");
assertEquals(userInfo.getEmail(), "wonwoo@test.com");
}
}
아주 심플하게 테스트를 할 수 있어서 좋은 것 같다. 오늘은 이정도면 기본적인 개념도 좀 더 알 듯 싶고 다음시간에는 좀 더 활용할 수 있도록 Spring 혹은 mockito를 이용해서 테스트를 할 수 있도록 해보자.
물론 전체
소스도 여기에 있다. 좀 더 많은 소스가 있으니 차근차근 살펴봐도 될 듯 싶다.