Mock argument matcher 에러 고찰과 해결

김건우·2023년 1월 4일
0

Junit / TDD

목록 보기
4/4
post-thumbnail

요새 진행하는 개인프로젝트에서 2주간은 RestApi와 Exception 의 예외 처리와 상태코드 반환 등 Exception Handeler 에 집중 했었다면 지금은 현재 컨트롤러와 서비스의 TDD 그리고 Junit5를 이용한 테스트 코드에 집중하고있다. 그 중 하나의 문제를 직면했다 바로.

Mock argument matcher

Mock argument matcher 의 에러를 서비스 테스트를 진행하다가 만나는 것이었다. 우선 다음과 같은 코드의 서비스 코드를 보여주겠다.

밑의 테스트코드는 Fixture를 사용하여 when()과 returnThen()에 서비스에서 사용되는 repository를 가정을 해준다. 왜냐하면 Mock 객체를 끌어다 쓰니까 말이다. 하지만 밑의 코드는 다음과 같은 에러를 만나게해준다.

 @Test
    @DisplayName("마이피드 보기 성공")
    void 마이피드_성공() throws Exception {

        AllFixture all = AllFixture.getDto();
        User user = UserEntityFixture.get(all.getUserName(), all.getPassword());
        Post post = PostEntityFixture.get(user);
        PageRequest request = PageRequest.of(0, 10, Sort.Direction.DESC, "registeredAt");

        when(userRepository.findOptionalByUserName(any())).thenReturn(Optional.of(user));
        when(postRepository.findPostsByUser(user, any())).thenReturn(Page.empty());

        Page<PostMineDto> myPeed = postService.getMyPeed(user.getUsername(), request);

        assertThat(myPeed.getTotalPages()).isEqualTo(1);
        assertDoesNotThrow(() -> myPeed);
    }
  • 위의 테스트 코드 진행 시 종종 만난 Mock argument matcher 에러 🔽
Invalid use of argument matchers!
2 matchers expected, 1 recorded:
-> at com.example.crudpersional.service.CommentServiceTest$MyPeed.마이피드_성공(CommentServiceTest.java:372)

위의 에러 코드의 내용의 뜻은 즉,**2개의 Matcher를 예상했는데 1개만 기록되었다는 얘기다.

그래서 다음과 같이 Stubbing 할 메서드의 모든 파라미터를 Matcher를 통해 전달해주면 에러가 발생하지 않는다.**
우선 해결 방법을 알아보기전 Mockito에서 지원해주는 any()를 알고넘어가자

any()

Java 8의 새로운 점은 표현식의 대상 유형이 하위 표현식의 유형 매개 변수를 유추하는 데 사용된다는 것이다. Java 8 이전에는 매개 변수 유추에 사용 된 메소드에 대해서만 인수가 사용된다. 이 경우의 매개 변수 유형은 doStuff의 대상 유형이 any()되고의 반환 값 유형은 any()해당 인수 유형과 일치하도록 선택되어지는 기능이다.

  • 장점
    좀더 다양한 인자에 대해서 테스트를 하고 싶을 때 eq나 any같은 argumentmatcher를 사용하는 것이다

나의 위의 테스트 코드를 보면 when() , thenReturn()을 사용한 repository의 메서드의 가정하는 when구간에서 인수로 실제 Fixture로 구현된 객체와 any() 메서드를 같이 매개변수로 사용한 것을 볼 수 있다.

when(postRepository.findPostsByUser(user, any())).thenReturn(Page.empty());

의 부분을 잘보면 any()만을 사용한 것이 아닌, 실제 테스트 픽스처 객체의 값도 넘겨 준것을 볼 수 있다

해결방법과 과정

서비스 메서드에 인자를 넘겨줄 때 argumentmatcher를 한 인자에 사용하면 다른 모든 인자도 argumentmatcher로 넘겨주어야 한다는 것이다.

  • 해결 코드 (둘다 any()로 넘겨주자)
when(postRepository.findPostsByUser(any(), any())).thenReturn(Page.empty());
  • 위와 같이 코드수정을 해준다면 다음과 같이 Mock argument matcher 에러를 만나지않고 테스트 통과를 할 수 있다.🔽
profile
Live the moment for the moment.

0개의 댓글