본문 바로가기

TIL/트러블슈팅

[SpringBoot] Wanted but not invoked 테스트 코드 시간 정보 비교

👉 문제 상황

Mockito에서 findTopArticles 메서드에 대한 호출을 예상 인자와 실제 호출된 인자가 정확히 일치하지 않아서 문제가 발생

오류 메시지 설명:

  • Wanted but not invoked 부분은 예상한 호출이 실제로 일어나지 않았다는 의미.
  • articleRepository.findTopArticles가 호출될 때 2025-02-11T23:40:27.674555400라는 시간이 예상되었지만, 실제로 호출된 시간은 2025-02-11T23:40:27.843202500로, 두 값이 다른 시간이야.

👉 에러 원인

LocalDateTime.now()의 시간 정확도 차이

  • LocalDateTime.now()를 사용해서 oneMonthAgo 값을 동적으로 설정했을 때 밀리초 단위로 값이 달라질 수 있음. 이로 인해 stubbing한 값과 실제 호출된 값이 일치하지 않아서 에러 발생

시간 비교의 정확도 문제 해결

  • Mockito에서 시간 비교 시, 정확한 LocalDateTime 값을 사용하는 대신 any(LocalDateTime.class)로 처리했기 때문에, 실제 호출된 시간과 stubbing한 값의 밀리초 차이로 에러가 발생

👉해결 방법

 1. 시간 비교 시 eq() 대신 any(LocalDateTime.class) 사용

  • any(LocalDateTime.class)를 사용해 시간에 관계없이 테스트하도록 수정.

2. 정확한 시간 값 사용

  • LocalDateTime 객체를 LocalDateTime이 아니라 any(LocalDateTime.class)로 처리해도 정상 동작하도록 수정.

3. ArgumentCaptor로 시간 값 캡처 후 확인

  • ArgumentCaptor를 사용해 실제로 호출된 시간 값을 검증하도록 변경할 수도 있음.
// ArgumentCaptor로 실제 값 캡처
        ArgumentCaptor<LocalDateTime> captor = ArgumentCaptor.forClass(LocalDateTime.class);
        verify(articleRepository, times(1)).findTopArticles(captor.capture(), any(PageRequest.class));

        // 실제 호출된 LocalDateTime 값을 초 단위까지 비교
        assertThat(captor.getValue().truncatedTo(ChronoUnit.SECONDS))
                .isEqualTo(oneMonthAgo.truncatedTo(ChronoUnit.SECONDS));    }