본문 바로가기
Java/Spring with Error

[해결 방법] TooManyActualInvocations

by HJ0216 2024. 9. 22.

org.mockito.exceptions.verification.TooManyActualInvocations

Environment
Language: Java 17
Framework: SpringBoot 3.1.0, Junit5
DB: MySQL, Redis

 

 

오류

org.mockito.exceptions.verification.TooManyActualInvocations: 
userService bean.create(
    refEq(cohttp://m.msgs.domain.user.dto.SignUpRequestDTO@69bf351e)
);
Wanted 1 time:
-> at cohttp://m.msgs.domain.user.service.UserService.create(UserService.java:41)
But was 2 times:
-> at cohttp://m.msgs.domain.user.controller.UserControllerTest.setup(UserControllerTest.java:45)
-> at cohttp://m.msgs.domain.user.controller.UserController.create(UserController.java:30)

UserService의 create 메서드가 너무 많이 호출됨

1번을 의도했으나, 2번이 호출됨

 

 

원인

@SpringBootTest
@AutoConfigureMockMvc(addFilters = false)
class UserControllerTest {
    @BeforeEach
    void setup() {
        SignUpRequestDTO signUpDto = SignUpRequestDTO.builder()
                .status("M")
                .email("temp@email.com")
                .phone("01023698745")
                .nickname("name")
                .password("temp123!")
                .confirmPassword("temp123!")
                .build();

        userService.create(signUpDto);
    }

    @Test
    @DisplayName("Controller: 회원 가입 실패, 중복된 이메일")
    void createFailDuplicateEmail() throws Exception {
        // given
        SignUpRequestDTO signUpDto = SignUpRequestDTO.builder()
                .status("M")
                .email("temp@email.com")
                .phone("01023698745")
                .nickname("name")
                .password("temp123!")
                .confirmPassword("temp123!")
                .build();

        // when // then
        mockMvc.perform(post("/api/v2/users/new")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(signUpDto)))
                .andExpect(status().isBadRequest())
                .andExpect(jsonPath("$.errorMessage").value("이미 존재하는 이메일 입니다."));

        // 회원 생성 메소드가 호출되었는지 확인
        verify(userService).create(refEq(signUpDto));
    }
}

중복 회원 검사를 위해 Test전 @BeforeEach를 사용해서 UserService의 create 메서드를 호출

+ 중복회원 검증 시, UserService의 create 메서드를 호출

→ 총 create 메서드 2회 호출

→  verify 메서드에서 예상 호출 수와 실제 호출 수의 불일치가 발생하여 TooManyActualInvocations 예외 발생

 

 

해결

@SpringBootTest
@AutoConfigureMockMvc(addFilters = false)
class UserControllerTest {
    @Test
    @DisplayName("Controller: 회원 가입 실패, 중복된 이메일")
    void createFailDuplicateEmail() throws Exception {
        // given
        SignUpRequestDTO signUpDto = SignUpRequestDTO.builder()
                .status("M")
                .email("temp@email.com")
                .phone("01023698745")
                .nickname("name")
                .password("temp123!")
                .confirmPassword("temp123!")
                .build();

        // Mocking 중복된 이메일로 인한 예외 발생
        doThrow(new BusinessException(ErrorCode.DUPLICATED_EMAIL))
                .when(userService).create(any(SignUpRequestDTO.class));

        // when // then
        mockMvc.perform(post("/api/v2/users/new")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(signUpDto)))
                .andExpect(status().isBadRequest())
                .andExpect(jsonPath("$.errorMessage").value("이미 존재하는 이메일 입니다."));

        // 회원 생성 메소드가 호출되었는지 확인
        verify(userService).create(refEq(signUpDto));
    }
}

@BeforeEach를 제거하고 doThrow() 활용

* userService의 create 메서드로 SignUpRequestDTO가 넘겨지면 DUPLICATED_EMAIL Exception 호출로 모킹

 

 

 

📑

참고 자료