Junit5 + Mockito를 함께 사용하는 예제를 준비했습니다.
배경
Mockito 사용 시 특정 메서드가 수행됐는지 확인하기 위해 verify()를 사용하는 경우가 많다.
보통 이런 식으로 많이 사용할 것이다.
verify(mock).doSomething(any(Person.class));
이 때 메서드에 전달되는 파라미터 값까지 동일한지 확인하고 싶다면 어떤 방법이 있을까?
(any()로 검증하는건 타입만 확인하는 것이라 불안하다.)
ArgumentMatcher로 검증하기
ArgumentMatcher 를 implements 혹은 익명 객체로 생성하여 파라미터를 검증할 수 있다.
verify(list, times(2)).add(argThat(new ArgumentMatcher<String>(){
public boolean matches(String arg) {
return arg.length() < 5;
}
}));
간단하게 람다로 사용할 수도 있다.
verify(list, times(2)).add(argThat(string -> string.length() < 5));
ArgumentCaptor로 검증하기 (Since 1.8.0)
이름에서도 유추할 수 있듯이 인수를 캡쳐하는 역할을 한다.
ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
verify(mock).doSomething(argument.capture());
assertEquals("John", argument.getValue().getName());
verify 하려는 메서드의 인수들을 캡쳐하고 assert 문에서 검증할 수 있다.
ArgumentCaptor를 간단히 초기화하고 싶다면 '@Captor' 를 사용할 수도 있다. (Since 1.8.3)
@ExtendWith(MockitoExtension.class)
public class TestClass {
@Captor
private ArgumentCaptor<Person> captor;
}
주의할점
1. verify() 내에서는 capture() 메서드를 사용해야 한다. 해당 인수를 캡쳐 후 assert문에서 getValue()로 검증해야 한다.
2. stubbing에 같이 사용하지 말 것.
- captor가 then(결과 확인) 블록 외부에 생성되므로 테스트 가독성이 저하될 수 있음.
- stubbing 메서드가 호출되지 않은 경우에는 인수가 캡쳐되지 않으므로 결함 발견이 힘들 수 있음.
- stubbing에는 ArgumentMatcher를 사용하는 것이 더 적합하다.
ArgumentMatcher보다 ArgumentCaptor가 적합한 경우
- 생성한 ArgumentMatcher가 재사용되지 않는 경우 → ArgumentMatcher를 람다로 대체하면 재사용되지 않는 문제는 해결될 것 같다.
- 검증을 완료하기 위해 argument value를 assert 내에 포함해야하는 경우
- (개인적 의견) 검증해야할 파라미터가 주소 값이 다른 객체인 경우
- ArgumentMatcher를 사용하면 matches() 구현 아래 객체 내 필드들이 동등한지 비교하는 로직이 들어가야 하는데, ArgumentCaptor를 사용하면 usingRecursiveComparision()를 사용하여 쉽게 동등성을 확인할 수 있을 것 같다.
- 객체 내에 equals&hashCode를 재정의하면 ArgumentMatcher로도 쉽게 사용할 수 있을테지만, 테스트에서만 사용하는 코드라면 재정의하는 것이 부적합할 수 있다.
ArgumentMatcher 사용
verify(list, times(2)).add(argThat(person -> {
return person.getName.equals("name") && person.getAge(20) && ...
}));
ArgumentCaptor 사용
Person expected = new Person("name", 20, ...);
verify(mock).doSomething(argument.capture());
assertThat(argument.getValue()).usingRecursiveComparison().isEqualTo(expected);
Verification with assertions (Since 5.3.0)
verify 내에서 assert 문을 활용할 수 있는 방법이다.
verify(serviceMock).doStuff(assertArg(param -> {
assertThat(param.getField1()).isEqualTo("foo");
assertThat(param.getField2()).isEqualTo("bar");
}));
참고자료
- https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html
'개발 > 기타' 카테고리의 다른 글
nullable한 값을 반환하는 집계함수 (0) | 2022.10.14 |
---|---|
Ubuntu 서버에 Docker로 스프링부트 Jar 배포 (feat Redis) (0) | 2022.01.06 |
[erwin] forward engineering (0) | 2021.07.02 |
[Maven/JSP/파이썬] 파이썬 Client에서 JSP Server로의 파일 데이터 전송(feat. MultipartRequest) (0) | 2021.03.27 |
aws 우분투 리눅스 tomcat9 서버에 war 파일 배포하기 (0) | 2021.01.22 |
이전 댓글