발단
나는 Jwt 토큰 발급(JwtTokenClient.class)에 대한 단위 테스트를 작성하고 있었다.
테스트 코드
package com.hangongsu.infrastructure.client.auth.jwt;
import com.hangongsu.core.dto.auth.response.TokenResponse;
import com.hangongsu.support.property.jwt.JwtProperty;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
class JwtTokenClientTest {
private JwtProperty jwtProperty = new JwtProperty(
"issuer",
"secretKeysecretKeysecretKeysecretKeysecretKeysecretKeysecretKey",
"1000"
);
private JwtTokenClient jwtTokenClient = new JwtTokenClient(jwtProperty);
@BeforeEach
void setup() {
jwtTokenClient.afterPropertiesSet();
}
@Test
void 유저_정보를_통해_엑세스_토큰을_발급할_수_있다() throws Exception {
// given
Long userId = 1L;
TokenResponse token = mock(TokenResponse.class);
// 여기서 에러 발생
given(jwtTokenClient.createAccessToken(userId)).willReturn(token);
// when
TokenResponse result = jwtTokenClient.createAccessToken(userId);
// then
assertThat(result).isNotNull();
assertThat(token).isEqualTo(result);
}
}
테스트 코드를 실행했을 때, given(jwtTokenClient.createAccessToken(userId)).willReturn(token); 이 부분에서 에러가 발생했다. 에러 메세지는 다음과 같았다.
문제 발생
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.
at com.hangongsu.infrastructure.client.auth.jwt.JwtTokenClientTest.유저_정보를_통해_엑세스_토큰을_발급할_수_있다(JwtTokenClientTest.java:33)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Process finished with exit code 255
org.mockito.exceptions.misusing.MissingMethodInvocationException는 Mockito가 when() 또는 given() 구문에 전달된 메서드 호출이 모의(mock) 객체의 메서드가 아닌 경우에 발생한다.
Mockito를 사용할 때 given(), when() 등의 스터빙(stubbing) 메서드를 쓸 때는 그 객체가 Mocking된 객체여야만 한다.
하지만 나는 JwtProperty와 JwtTokenClient를 직접 생성한 인스턴스로 만들어 테스트 코드를 작성하고 있었기 때문에 이와 같은 에러가 발생하였다.
따라서 코드를 다음과 같이 수정하여서 mocking을 적용하였다.
시도
1차 시도
class JwtTokenClientTest {
private JwtTokenClient jwtTokenClient = mock(JwtTokenClient.class);
@Test
void 유저_정보를_통해_엑세스_토큰을_발급할_수_있다() throws Exception {
// given
Long userId = 1L;
TokenResponse token = mock(TokenResponse.class);
given(jwtTokenClient.createAccessToken(userId)).willReturn(token);
// when
TokenResponse result = jwtTokenClient.createAccessToken(userId);
// then
assertThat(result).isNotNull();
assertThat(token).isEqualTo(result);
}
}
필요없는 코드를 싹 제거하고 jwtTokenClient의 초기화를 Mockito의 mock() 메서드를 통해 위임했다.
그리고 실행한 결과,, 에러 메시지는 없어지고 성공했다!
성공
결론
- Mockito의 사용법을 잘 숙지하자!
'Kotlin & Java' 카테고리의 다른 글
@WebMvcTest EntityManagerFactory 빈 주입 이슈 - A component required a bean named 'entityManagerFactory' that could not be found. (0) | 2024.08.22 |
---|---|
코틀린 코딩 컨벤션 (3) | 2023.12.18 |
코틀린의 자료형과 자바의 자료형 (1) | 2023.12.07 |
코틀린의 Property를 자바 Field로 디컴파일 해보자 (0) | 2023.12.05 |
코틀린의 생성자 (0) | 2023.12.05 |