문제: 사용자 정보 업데이트에 대한 test case 작성시 아래와 같은 에러로 test fail
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/native/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/native/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
에러 요약: when()은 반드시 Mock객체의 메서드 호출에 대해 작동해야하는데 Mock객체가 아닌 다른 객체에 대해 호출하고 있어서 에러가 나옴.
문제의 when()
when(userService.getCurrentUserEmail()).thenReturn(email);
여기서 궁금한건 앞서 when()을 사용해서 다른 기능들의 test들은 통과가 되었었다.
에러 없이 통과한 when()
when(userRepository.findByEmail(email)).thenReturn(Optional.empty());
왜 userService.getCurrentUserEmail() 메소드를 사용하려고 하니 에러가 난걸까?
에러 원인: when()은 반드시 Mock 객체의 메서드 호출에 대해 작동한다. (@Mock) 내가 userService에 해놓은 애노테이션은 @InjectMocks 였다.
@InjectMocks
private UserService userService;
그전에도 when()을 사용했지만 .getCurrentUserEmail()에서 에러가 난 이유
userService.getCurrentUserEmail() 호출이 Mock 객체에 대한 메서드 호출이 아니라 실제 객체에 대한 호출이기 때문이다.
기본적으로 when()은 Mock 객체에 대해 메서드를 호출하는 경우에만 동작한다.
즉, Mock 객체가 아닌 실제 객체에 메서드 호출을 하려고 하면 Mockito는 이를 인식하지 못하고 MissingMethodInvocationException 예외를 던진다.
UserRepository는 @Mock로 선언해 놓았다.
@Mock
private UserRepository userRepository;
해결: @Spy 애노테이션을 추가하여 실제 메소드 일부를 Mocking하자
@Spy는 Mockito에서 제공하는 어노테이션으로, 실제 객체를 감시하고 특정 메서드만 Stub(대체) 처리할 수 있도록 해준다.
즉, @Spy는 실제 객체를 생성하고, 해당 객체의 일부 메서드만 Mock 처리하는 방식이다.
@Spy와 @Mock의 차이점
- @Mock: 객체의 모든 메서드를 Mock 처리한다. Mock 객체는 실제 동작을 하지 않고, 설정된 값만 반환 한다.
- @Spy: 실제 객체를 사용하며, 일부 메서드만 Stub(대체)할 수 있다. 즉, 실제 객체의 동작과 Mocking을 결합할 수 있다.
@Spy를 추가하고 테스트 성공!
> Task :test
BUILD SUCCESSFUL in 5s
4 actionable tasks: 2 executed, 2 up-to-date
8:11:54 PM: Execution finished ':test --tests "com.lima.consoleservice.domain.user.service.UserServiceTest.updateUser"'.
정리
UserService는 의존성을 주입받는 객체여 @Mock가 아니라 @InjectMocks 로 사용해야하기 때문에 @Spy를 추가해줌으로써 해당 에러를 해결하였다.
@Spy
@InjectMocks
private UserService userService;
** 그냥 하루하루 개인 공부한 것을 끄적 거리는 공간입니다.
이곳 저곳에서 구글링한 것과 강의 들은 내용이 정리가 되었습니다.
그림들은 그림밑에 출처표시를 해놓았습니다.
문제가 될시 말씀해주시면 해당 부분은 삭제 하도록하겠습니다. **
'개발일기 > project' 카테고리의 다른 글
[Troubleshooting] #4 docker로 띄운 elasticsearch 노드 구성 (0) | 2025.02.05 |
---|---|
[Troubleshooting] #2 JPA의 동작과 WARN 레벨 로그 수정 (0) | 2025.01.14 |
[Troubleshooting] #1 Docker로 Elasticsearch node 2개 띄우기 (1) | 2025.01.13 |
[Jenkins] Docker로 띄운 Jenkins에 git 연결하기 (0) | 2025.01.11 |
[Jenkins] Docker에 Jenkins 실행하기 (0) | 2025.01.11 |
댓글