Mockito 사용하기

알파로그·2023년 6월 24일
0
post-custom-banner

✏️ Mock

  • 테스트 할 때 필요한 실제 객체를 흉내내는 가짜 객체를 만들어 테스트의 효율을 높히기 위해 사용한다.
    • 서비스 로직의 부하가 많이걸려, 시간도 너무 오래걸리는 경우
    • 서버간 통신이 제대로 되고있는지 확인해야하는 경우
    • 요청을 보낼 API 가 작업중인 경우 등등 ...

✏️ Mock 객체의 종류

📍 Stubbing

  • Mock 객체를 통해 반환될 미리 준비된 답변을 뜻한다.
    • Stub 이라고도 불린다.
  • when method 를 사용해 Stubbing 을 사용한다.
    • when 에 stubing 할 method 를 넣고 method chaining 형식으로 사용된다.

📍 @Mock

  • 가짜 객체를 뜻한다.
  • 객체의 method 를 호출하려면 반드시 stubbing 을 해야한다.
    • 만약 Stubbing 을 생략할경우 Null 또는 0 을 반환한다.

📍 @Spy

  • Spy 로 만든 객체는 진짜 객체를 뜻한다.
  • Stubbing 을 하지 않는다면 원래 객체의 반환값을,
    한다면 Stubbing 한 값을 반환한다.

📍 @InjectMock

  • DI 를 Mock 이나 Spy 로 생성된 Mock 객체를 자동으로 주입해주는 어노테이션이다.

📍 MockBean

  • Mock 객체를 Bean 으로 등록하는 기능

✏️ Mockito 적용

📍 Dependency

testImplementation 'org.mockito:mockito-core:3.11.2' // mockito

📍 Test case

  • Mockito 를 사용하기 위해선 Test 객체에 어노테이션을 선언해줘야 한다.
@SpringBootTest
@Transactional
@ExtendWith(MockitoExtension.class)
@RunWith(MockitoJUnitRunner.class)
class StudyServiceTest {
  • 응답을 제어해야 하는 method 를 포함한 객체를 Mock Bean 으로 생성해준다.
@MockBean private MemberClient memberClient;
  • Mock Bean 으로 생성한 객체의 method 를 Stubbing 해준다.
    • 모든 test 를 대상으로 Mock 객체가 필요할 경우 BeforeEach 를 사용하면 중복을 제거할 수 있다.
@BeforeEach
public void beforeEach() {
    when(memberClient.updateMyStudy(any()))
            .thenReturn(new RsData<>("S-1", "성공", null));
}
  • 이제 평소처럼 Test 를 작성하면된다.
    • Stubbing 한 객체를 직접적으로 호출하지 않고 다른 method 를 통해 간접적으로 호출하게 되어도 subbing 한 결과가 반환되게 된다.
@Test
@DisplayName("mockito test")
void no0() {
    MyStudy myStudy = studyService.create(CreateReqDto.createStudy(1L, "name", "about", "leader", 10));
    Study study = studyService.findById(myStudy.getStudy().getId());

    assertThat(study.getName()).isEqualTo("name");
}

📍 any() 사용법

  • api 의 파라미터에 모든 객체를 뜻하는 any() 는 기본형 데이터타입을 해석할 수 없다.
    • int 는 anyInt() 로, String 은 anyString() 으로 수정해야한다.
  • any 말고 특정 값을 지정해야 할 땐 eq() 를 사용하면 된다.
when(studyClient.findInput(eq("study"), anyInt(), anyString()))
                .thenReturn(new RsData<>("S-1", "성공", list));
  • 특정 값을 제외하고 반환값을 만드려면 argTat(s -> !s.equals()) 를 사용하면 된다.
when(studyClient.findInput(argThat(s -> !s.equals("study")), anyInt(), anyInt()))
                .thenReturn(new RsData<>("S-1", "성공", new ArrayList<>()));

📍when 절에서 조건문 만들기

@BeforeEach
void beforeEach() {
    MemberResDto dto = new MemberResDto("test123");

    when(memberClient.findById(any()))
            .thenAnswer(invocation -> {
                Long memberId = (Long) invocation.getArgument(0);

                if (memberId == 2L)
                    return new RsData<>("S-1", "성공", dto);
                else if (memberId == 3L)
                    throw new BadRequestException();

                dto.setBaekJoonName("test123");
                return new RsData<>("S-1", "성공", dto);
            });
}
profile
잘못된 내용 PR 환영
post-custom-banner

0개의 댓글