스프링부트 – @MockBean


– 개요
– 테스트 더블
– 목빈
– 마치다


단위 테스트가 아닌 통합 테스트를 사용하면 일반적으로 여러 리포지토리와 비즈니스 로직이 함께 있기 때문에 많은 불편을 겪었을 것입니다.

예를 들어 다음과 같은 문제가 있습니다.

  • 불필요한 데이터 생성
  • 실제 시험에 집중할 수 없습니다.

  • 태스크 코드 실행 시간 증가.
  • 상황을 설정하는 번거 로움. (로그인, 권한 처리 등)

어쨌든 통합 테스트의 가장 큰 문제는 하나의 테스트에 너무 많은 코드가 필요하다는 것입니다.

다시 말해서,

  • 엔티티가 데이터베이스에 저장되려면 모든 필수 값을 채워야 합니다.

  • 저장소에서 검색하기 위해서는 엔티티 간의 모든 연결이 형성되어야 하며,
  • HttpSession 저장과 같은 작업이 외부 모듈에 추가됩니다.


위와 같은 문제가 발생한 후 테스트 코드와 주변 코드를 분리하는 방법이 있습니다.

목적에 따라 비슷하지만 다른 대상을 사용하는 모든 행위를 일컫는 테스트 복식의 활용이다.

대표적으로 Stub, Dummy, Mock, Spy 등이 있다.

(본 포스팅에서는 Mock만 사용)


위의 그림에서 보듯이 테스트의 범위를 테스트 더블로 대체하여 대상 코드 자체의 동작과 협력 객체의 동작으로 제한합니다.

테스트 복식의 장점은 다음과 같습니다.

  • 테스트 중인 코드 분리
  • 향상된 테스트 속도
  • 예측할 수 없는 실행 요소 제거
  • 특수 상황 테스트 가능
  • 숨겨진 정보 확인 가능

Mock은 쉘만 있는 객체입니다.

즉, Mock Bean은 이전에 사용했던 Bean의 Shell만 가져오고 내부 구현 부분은 모두 사용자에게 위험합니다.

따라서 Bean의 특정 메소드에 특정 값이 입력되면 개발자의 요구에 따라 특정 값이 반환되어야 하는 모든 내용을 조작할 수 있습니다.

코드를 보고 이해해 봅시다.

package kr.co.hhjpetclinicstudy.service.service;

import kr.co.hhjpetclinicstudy.persistence.entity.Owner;
import kr.co.hhjpetclinicstudy.persistence.repository.OwnerRepository;
import kr.co.hhjpetclinicstudy.service.model.OwnerCreators;
import kr.co.hhjpetclinicstudy.service.model.OwnerMapperImpl;
import kr.co.hhjpetclinicstudy.service.model.dtos.request.OwnerReqDTO;
import kr.co.hhjpetclinicstudy.service.model.mappers.OwnerMapper;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;

@ExtendWith(MockitoExtension.class)
public class BlogTest {

    @Autowired
    private OwnerService ownerService;

    @MockBean(name = "ownerRepository")
    private OwnerRepository ownerRepository;

    @MockBean
    private OwnerMapper ownerMappers;

    @Test
    @DisplayName("Owner 등록 - 성공")
    void createUser_success() {

        //given
        final OwnerReqDTO.CREATE create = OwnerCreators.ownerReqDto_create_creators();
        final Owner owner = OwnerMapperImpl.toOwnerEntity(create);

        given(ownerMappers.toOwnerEntity(any(OwnerReqDTO.CREATE.class))).willReturn(owner);
        given(ownerRepository.existsByTelephone(any(String.class))).willReturn(false);

        //when, then
        assertDoesNotThrow(() -> ownerService.createOwner(create));
    }
}
  • @MockBean
    • 기존 Spring bean이 아닌 MockBean을 주입한다.

    • 주석 내부에 문자열 값을 등록하는 것은 기존에 선언된 빈 객체를 덮어쓰는 것입니다.

    • bean 이름을 강제로 지정하지 않으면 Spring은 가져올 bean을 알 수 없습니다.

  • 주어진(…)
    • 해당 Mock Bean이 어떤 조치를 취했을 때 어떤 결과를 반환할지 선언하는 부분이다.

    • given(ownerRepository.existsByTelephone(any(String.class))).willReturn(false);
      • 예를 들어 위의 코드에서는 String.class 유형의 모든 값이 false로 반환됨을 의미합니다.

이렇게 테스트 코드를 실행하면 테스트 실행 시 테스트 코드에 선언된 Mock Bean이 주입되어 실행된다.


그것을 요 ​​약하기,

Mock은 테스트할 메서드의 유효성 검사를 무시하도록 설정할 수 있습니다.

경우에 따라 외부 API와 상호 작용할 필요 없이 테스트를 수행할 수 있습니다.

또한 데이터베이스에 데이터를 입력하지 않고 불필요한 필드 데이터를 입력하지 않고 테스트를 수행할 수 있습니다.

물론 모의 테스트만으로 모든 테스트를 수행할 수 있는 것은 아닙니다.

통합 테스트 코드는 당연히 필요하므로 모든 메소드를 일반 코드처럼 테스트하는 코드도 필요하다.

하지만 단위 테스트로 테스트할 때는 적극적으로 활용하는 것이 좋다.


참조 : https://jojoldu.226

SpringBoot @MockBean, @SpyBean 소개

안녕하세요? 이번에는 SpringBoot의 @MockBean 및 @SpyBean 예제를 살펴보겠습니다.

모든 코드는 Github에 있으니 같이 보시면 이해가 쉬울 것 같습니다.

(공부한 내용을 정리한 Github,

jojoldu.tistory.com