Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

모킹할 때 테스트 검증에 필요하지 않은 값들은 Mockito ArgumentMatchers로 대체해도 될까? #11

Open
Yiseull opened this issue Feb 28, 2024 · 2 comments
Assignees
Labels
completed test Further information is requested

Comments

@Yiseull
Copy link
Owner

Yiseull commented Feb 28, 2024

📍 상황

서비스 테스트를 진행하면서, 검증이 필요하지 않은 값들을 어떻게 처리해줘야 할지 고민이 생겼다.

1. 반환 값으로 ArgumentMatchers를 사용해도 될까?

예를 들어, 투표 생성 기능을 테스트 할 때 로그인한 회원의 Id를 반환하는 메서드를 모킹하고 있다. 이 경우 회원 Id는 테스트에 큰 영향을 미치는 정보는 아니라고 생각한다. 왜냐하면 회원 Id가 어떤 값이든, 투표가 주어진 정보로 잘 생성되는지만 확인하면 되기 때문이다. 그래서 현재 로그인한 회원 Id를 반환하는 메서드의 반환 값으로 실제 값을 사용하는 것이 아니라, Mockito의 ArgumentMatchers인 anyLong()를 사용해도 되는지 고민이 되었다.

// given
 given(memberUtils.getCurrentMemberId())
				.willReturn(1L); // 1L -> anyLong()을 사용해도 될까?

2. 테스트 실행 부분에서 필요하지 않은 입력 값에 대해 ArgumentMatchers를 사용해도 될까?

GWT(Given-When-Then) 구조의 테스트에서 When 부분의 코드에서 중요하지 않은 입력값에 대해 ArgumentMatchers를 사용해도 되는지 고민이 되었다.

아래는 투표 참여 테스트에 대한 실행과 검증 부분이다. 이 테스트는 종료된 투표에 참여할 수 없다는 것을 검증하고 있다. 여기서 투표 아이템 Id는 중요한 정보가 아니라고 생각했다. 이때 아이템 Id인 1L을 anyLong()으로 변경해도 될까?

// when & then
assertThatThrownBy(() -> voteService.participateVote(voteId, 1L)) // // 1L -> anyLong()을 사용해도 될까?
				.isInstanceOf(BusinessException.class)
				.hasFieldOrPropertyWithValue("errorCode", ErrorCode.VOTE_CANNOT_PARTICIPATE);

📍 결론 - 모두 불가능

Java 공식 문서에 따르면, ArgumentMatchers는 검증 또는 스텁(stub) 메서드 외에는 사용할 수 없다고 한다. 또한 반환 값으로 사용할 수 없다. 반환 값이나 테스트 실행 부분의 입력 값으로 ArgumentMatchers를 사용하려고 하면 InvalidUseOfMatchersException 예외가 발생한다.

👉 ArgumentMatchers를 사용할 때는 목적대로 사용하자.

참고

@Yiseull Yiseull self-assigned this Mar 1, 2024
@Yiseull Yiseull added the test Further information is requested label Mar 1, 2024
@Yiseull
Copy link
Owner Author

Yiseull commented Mar 1, 2024

ArgumentMatchers 사용 시 주의사항에 대해 간결하게 정리해보았다.

  1. 메서드에 인수가 두 개 이상 있는 경우 인수 중 일부에만 ArgumentMatchers를 사용할 수는 없다. 즉, ArgumentMatchers를 사용할 때는 모든 인수에 대해 사용하거나, 아예 사용하지 않아야 한다.

실제 프로젝트를 하면서 특정 인수는 실제 값을 사용하고, 다른 인수에는 any()를 사용해서 InvalidUseOfMatchersException를 겪은 적이 있다. 이런 경우에는 실제 값을 eq() 메서드로 감싸서 사용해야 한다.

  1. ArgumentMatchers는 반환 값으로 사용할 수 없다.
  2. 검증이나 스텁 이외의 위치에서는 ArgumentMatchers를 사용할 수 없다.

@Yiseull
Copy link
Owner Author

Yiseull commented Mar 1, 2024

회고

사실 이번 고민이 필요 없었을 수도 있다. 만약 직접 테스트 코드를 작성하고 실행해봤다면, 예외가 발생하면서 ArgumentMatchers를 사용할 수 없다는 것을 바로 알았을 것이다. 고민하고 자료를 찾아보는 시간보다 훨씬 빠르게 문제를 해결했을 수도 있다.

그러나 이번 고민을 통해 중요한 교훈을 얻었다. 고민하는 것도 중요하지만, 때때로 '일단 해보는 것'이 더 효울적인 해결책이 될 수 있을음 깨달았다. 이렇게 보면, 이번 고민은 시간 낭비가 아니라, 더 나은 개발자로 성장하는 과정의 일부였다고 생각한다. 이런 경험은 앞으로의 개발 과정에서 '일단 해보기'라는 선택지를 고려하는 데 도움이 될 것이다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
completed test Further information is requested
Projects
None yet
Development

No branches or pull requests

1 participant