BACKEND/JAVA & SPRING

@SpringBootTest, @MockBean, Mockito, Junit 등 테스트에 대해서…

이-프 2024. 12. 15. 15:15

MockMvc?

  • MockMvc란
    • MVC에 관련된 Mock 가짜 객체
    • 웹 어플리케이션을 서버에 배포하지않고, 테스트용 MVC 환경을 만들어서 요청 및 전송, 응답 기능을 제공해주는 객체
    • MockMvc를 통해 @Autowired로 주입받아서 사용 가능

 

@SpringBootTest

  • SpringApplication을 통해서 테스트에서 사용할 ApplicationContext를 쉽게 생성할 수 있습니다.
  • 그러므로, @SpringBootAplication이 붙은 어노테이션을 찾아 하위의 모든 빈들을 scan하기 때문에 애플리케이션에 정의된 모든 빈을 생성하여 ‘실행 시 느려질 수 있으므로, 단위 테스트에서는 적합하지 않다.’
@SpringBootTest
@AutoConfigureMockMvc //SpringBootTest에서는 MockMvc 객체를 사용하려면 해당 어노테이션 선언 필요
class SpringBootTest {

    @Autowired
    MockMvc mockMvc; // 주입 O
}
@SpringBootTest
@AutoConfigureMockMvc
class SpringBootTest {

    @Autowired
    MockMvc mockMvc; // 주입 O

    @Autowired
    UserController userController; // 주입 O

    @Autowired
    UserRepository userRepository; // 주입 O

    @Autowired
    UserService userService; // 주입 O
}

@WebMvcTest

  • Web Layer 관련 빈들만 등록하므로, @Component로 등록된 리포지토리와 서비스는 주입이 되지 않는다.
  • Web Layer = Security, Filter, Interceptor, Handling, Controller
  • 그러므로, 이외는 @MockBean 을 통해 주입받아야한다.
  • @MockBean = Spring Application Context에 Mock 객체를 빈으로 등록하는데 사용되는 annotation
@WebMvcTest
class SpringBootTest {

		@Autowired
		MockMvc mockMvc; // 주입 O

		@Autowired
		UserController userController; // 주입 O

		//@Autowired
		@MockBean
		UserRepository userRepository; // 주입 X

		//@Autowired
		@MockBean
		UserService userService; // 주입 X
}


Java 단위의 Unit Test (단위 테스트)

  • JUnit5 : 자바 단위 테스트를 지원하는 ‘테스팅 프레임워크’
  • AseertJ : .. ‘라이브러리’

 

given/when/then 패턴

  • given : 어떤 데이터가 준비되었을 때
  • when : 어떠한 함수를 실행하면
  • then : 어떠한 결과가 나와야한다

 

Mockito

개발자가 동작을 직접 제어할 수 있는 ‘가짜 객체’를 지원하는 테스트 프레임워크

  • Spring은 여러 객체들 간의 의존성이 발생하는데, 이러한 의존성은 단위 테스트 작성을 어렵게 한다.
  • 이를 해결하기 위해, 가짜 객체를 주입시키는 Mockito 라이브러리를 활용할 수 있다.
  • 가짜 객체에 원하는 결과를 Stub (하향식 테스트) 단위 테스트 가능
    • => 가짜 객체를 주입하여 어떤 결과를 반환하라고 준비해야함  
    • doReturn() : 가짜 객체가 특정한 값을 반환하는 경우
    • doNothing() : 가짜 객체가 아무 것도 반환하지 않는 경우 (void)
    • doThrow() : 가짜 객체가 예외를 발생시키는 경우

 

  • @Mock : 가짜 객체를 만들어 반환
  • @InjectMocks : 가짜 객체를 자동으로 주입시켜주는 어노테이션
  • example) @Mock을 통해 가짜 서비스 생성 후, @InjectMocks 를 통해 Controller에 이를 주입할 수 있다.

 

  • SpringBoot 2.2.0부터 공식적으로 JUnit5를 지원함에 따라, 이제부터는 @ExtendedWith(MockitoExtension.class)를 사용해야 결합이 가능하다.
@Transactional
@ExtendWith(MockitoExtension.class)
class ProductServiceTest {

    @InjectMocks //@Mock으로 생성된 가짜 객체들을 주입받음 (테스트해야할 서비스)
    private ProductService productService; 
    @Mock
    private MemberService memberService;
    @Mock
    private MemberRepository memberRepository;
    @Mock
    private ReservationRepository reservationRepository;
    @Mock
    private ProductRepository productRepository;
    @Mock
    private SecurityUtil securityUtil;

각 Layer 별 Test 범위

  • Controller: @WebMvcTest는 웹 계층을 테스트하며, 유닛 테스트라기보다는 웹 통합 테스트에 가까운 테스트입니다.
  • Repository: @DataJpaTest는 JPA 리포지토리데이터베이스의 상호작용을 테스트하며, 이는 통합 테스트에 속합니다.
  • Service: @ExtendWith(MockitoExtension.class)와 @Mock을 사용하는 서비스 계층 테스트는 유닛 테스트로, 비즈니스 로직만 검증하는 데 중점을 둡니다.

 

 

  WebMvcTest SpringBootTest Junit 단위(클래스/메소드) 테스트
목적 웹 계층(Controller)만 테스트 전체 애플리케이션(서비스, 리포지토리 등) 통합 테스트 단위(클래스/메소드) 테스트
테스트 범위 Controller, 필터 등 웹 관련 구성 요소만 테스트 전체 Spring 컨텍스트 로드, 실제 서버 및 DB와 연동 가능 특정 클래스나 메소드만 테스트, 외부 의존성 모킹
속도 빠름, 웹 계층만 로드 느림, 전체 애플리케이션 로드 매우 빠름, 독립적 테스트
주요 사용 목적 HTTP 요청과 응답 처리 테스트 (컨트롤러 테스트) 애플리케이션 전체 통합 동작 테스트
(서비스, DB 등)
특정 비즈니스 로직, 메소드 동작 검증
외부 의존성 외부 서비스는 @MockBean을 사용하여 모킹 실제 DB 및 외부 시스템과 통합될 수 있음 외부 의존성은 모킹하여 격리