발단
얼마전 LocalDate를 이용한 테스트 케이스를 작성하다가 고민이 생겼습니다.
테스트할 함수는 파라미터로 받은 LocalDate를 오늘날짜와 비교하는 함수였는데요 아래는 샘플코드입니다.
1 | public boolean isBeforeTarget(LocalDate targetDate) { |
날짜를 받고, 오늘 날짜랑 비교해서 오늘날짜가 targetDate 이전이면 true, 이후면 false를 리턴하게 되는데.
테스트 코드는 아래와 같습니다.
1 | private Utils utils = new Utils(); |
작성일 기준으로 오늘은 9월 7일이고, targetDate는 9월 8일이라 오늘은 targetDate 전 입니다. 그래서 true를 반환할거고 이 테스트코드는 통과하게 됩니다.
여기까지는 별 문제가 없었는데…
isBeforeTarget 함수에서 오늘을 기준으로 비교를 하다보니 이 테스트 코드는 내일부터는 fail로 바뀌게 될것입니다.
targetDate가 고정이라고 해도 LocalDate.now()가 매일매일 바뀔것이기 때문이죠.
그럼 테스트코드에서는 LocalDate.now()의 결과물이 항상 같은 날짜가 나오면 문제가 해결될거 같았습니다.
일반적으로 사용되는 @Mock 어노테이션을 이용해 LocalDate를 모킹하고 now 메소드 호출시에 임의의 날짜를 반환하게 작업하면 되겠지 라는 생각이었습니다.
1 |
|
아래와 같은 에러가 발생을 했는데요;
1 | org.mockito.exceptions.misusing.MissingMethodInvocationException: |
mockito에서 when 메소드의 인자값으로 ‘호출이 되는 메소드’를 넣어줘야하는데 static 메소드라 정상적으로 메소드를 인식하지 못하는거 같았습니다.
찾아보니 mockito를 이용해 static 메소드를 직접 모킹하는건 불가능하고 PowerMockito를 이용해야 한다고 나와있었습니다.
(* Mockito 3.4.0 이후 버젼에서는 PowerMockito 없이도 static 메소드 모킹이 가능하다고 합니다. 참고
PowerMocito를 이용해보자!
PowerMocito는 PowerMock의 확장 API라고 합니다. 그래서 PowerMock과 PowerMock API Mockito를 둘다 추가를 해줘야합니다.
1 | // build.gradle |
그리고 테스트 코드 클래스의 제일 상단에 아래 두개의 어노테이션을 추가해줘야합니다.
1 |
|
기존 테스트코드에 LocalData를 모킹하는 코드를 추가해줍니다.
1 |
|
이렇게 하면 언제 실행을 해도 now() 호출했을때 2021년 9월 1일로 고정이 되어서, 테스트코드가 항상 Pass 하는걸 확인 할 수 있습니다.
사용된 코드는 아주 간단한 예제로 LocalDate의 함수를 이용한 코드를 테스트 하였지만.
PowerMockito를 이용하면 다른 static 메소드나, private 메소드도 테스트가 가능할걸로 생각 됩니다.