관리 메뉴

제뉴어리의 모든것

테스트시 사용되는 각종 애노테이션 본문

Spring Boot

테스트시 사용되는 각종 애노테이션

제뉴어리맨 2022. 9. 13. 00:41

사전 지식

Mockito는 Mock 객체를 생성하고, 해당 Mock 객체가 진짜처럼 동작하게 하는 기능을 하는 Mocking framework(또는 라이브러리)이다.

 

@SpringBootTest

클래스 레벨에 붙이는 애노테이션.

@SpringBootApplication 이 붙은 클래스를 찾아서 해당 애노테이션의 기능을 활성화 시키면서, 실제로 애플리케이션을 띄운다. 그러므로 ApplicationContext가 활성화 되고

현재 프로젝트에서 빈으로 등록한 ( EX : @Component 가 붙은 클래스) 클래스들이 모두 ApplicationContext에 담기게 되는것이다.

 

그러므로, 실제 포트도 Listening되고 현재 애플리케이션의 Controller, Service, Repository 레벨 모두를 거치는 테스트 환경이 된다.

 

즉, 테스트를 실행시키면서 실제 애플리케이션을 띄움.

 

 

참조 : https://spring.io/guides/gs/testing-web/

https://blog.neonkid.xyz/272

 

[Spring boot] Spring 테스트 방법과 @SpringBootTest

서버 애플리케이션에서는 테스트 코드를 어떻게 구현해야 할까요? 제가 처음 서버 애플리케이션을 개발하고 나서 테스트 코드를 구현했을 때 가장 큰 의문점이 들었던 유형이었습니다. 클라이

blog.neonkid.xyz

 

Testing the Web Layer

this guide is designed to get you productive as quickly as possible and using the latest Spring project releases and techniques as recommended by the Spring team

spring.io

 

@AutoConfigureMockMvc

클래스 레벨에 붙이는 애노테이션으로

MockMvc의 자동 구성을 활성화하는 애노테이션.

즉, 테스트에서 쓰이는 MockMvc 타입의 구성을 자동으로 세팅해주는 애노테이션이라고 할 수 있다.

 

참조 : https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/autoconfigure/web/servlet/AutoConfigureMockMvc.html

 

AutoConfigureMockMvc (Spring Boot 2.7.3 API)

addFilters public abstract boolean addFilters If filters from the application context should be registered with MockMVC. Defaults to true. Returns: if filters should be added Default: true

docs.spring.io

 

 

+ 그렇다면 MockMvc 타입 (클래스) 란?

MockMVC란 Spring MVC 테스트 유틸리티 클래스. 테스트 코드를 작성하지 않는다면 Postman 등의 request를 발생시킬 수 있는 도구를 사용해 직접 호출해 서버를 디버깅해야 하는데 MockMVC를 사용하면 이 과정을 건너뛸 수 있다.

우리는 PostMan에서 단순이 Send 버튼을 누르거나, 웹브라우저에서 URL을 입력하고 엔터를 누르는 단순한 행동을 하겠지만, PostMan이나 웹브라우저는 내부적으로 뭔가 복작한 처리와 서버로 Request를 보내기 위해 여러 데이터를 세팅할 것이다. 그렇게 Request를 보내는 행위를 하는 도구가 MockMvc이고, 보내기 위해 세팅되어야할 데이터들을 세팅해 주는것이 @AutoConfigureMockMvc 애노테이션이라고 생각하면 될것이다.

쉽게 말해 Controller를 호출 가능하게 해주는 객체이다.

 

 

참조 : https://jayhooney.github.io/tdd/MockMvc/

 

MockMVC

How to use it ?

jayhooney.github.io

 

@MockBean (org.springframework.boot.test.mock.mocito.MockBean)

해당 애노테이션이 붙은 클래스를 실제 클래스 내용에 정의된 내용으로 빈으로 등록하는것이 아닌,

비어있는 껍데기의 빈을 생성하여 등록함.

아마도 이 애노테이션을 붙였다는것은 해당 필드의 클래스를 테스트 할 목적이 아닌!

해당 클래스는 테스트에 포함시키지 않기 위함일것이다.

예를들어 Controller 레벨만 테스트를 하고 싶어서 

Service 레벨의 객체에 해당 애노테이션을 붙여서 당연히 정상적인 결과를 뱉어낼 것을 given 메소드를 이용하여 정의를 할것이다.

 

참조 : https://www.baeldung.com/java-spring-mockito-mock-mockbean

 

Mockito.mock() vs @Mock vs @MockBean | Baeldung

Learn the differences between different types of Mocking with Mockito.

www.baeldung.com

 

@DataJpaTest

  • JPA에 필요한 클래스들만 로딩이 되어 좀 더 빠르게 테스트를 할 수 있다.
    • @Entity 어노테이션이 붙은 클래스
    • Spring Data JPA repository
  • DataSource의 설정이 정상적인지, JPA를 사용하여 데이터를 제대로 생성, 수정, 삭제하는지의 테스트가 가능하다.
  • @Transactional 어노테이션을 포함하고 있다. (테스트 완료되면 자동 Rollback)
  • 실제 데이터베이스에 테스트를 하고 싶은 경우 @AutoConfigureTestDatabase 어노테이션의 속성을 주면, 인메모리 데이터베이스가 아닌 실제 데이터베이스에 테스트가 가능하다.
    • @AutoConfigureTestDatabase 어노테이션은 기본적으로 내장된 임베디드 데이터베이스를 사용한다. (실제로 DataJpaTest 어노테이션을 사용할 경우에는 기본적으로 인메모리 데이터베이스가 존재해야 한다.)
    • Replace.NONE으로 설정하면 실제 데이터베이스에 테스트가 가능하다.

쉽게 말해, JPA Repository에 대한 테스트가 가능한 환경을 만들어 준다.

환경을 만들어 준다는것은 Repository 를 빈으로 등록해 준다는것이다.

그리고 현재 애플리케이션에 실제 DB를 연결하지 않았더라도,

내부 내장 DB를 가지고 있어서, 해당 DB를 이용하여 테스트를 가능하도록 해준다.

그리고 물론, 그 DB는 실제 사용할 DB 로 교체하여 테스트도 가능하다. 

그러므로 아래의 (2) 와 같이 의존성 주입을 받을 수 있다.

@DataJpaTest   // (1)
public class MemberRepositoryTest {
    @Autowired
    private MemberRepository memberRepository;   // (2)
    
    :
    :
}

JPA 환경 말고도 JDBC 사용환경에서의 Repository 테스트를 해보고 싶다면 @DataJdbcTest 같은 애노테이션을 사용하면 된다.

 

참조 : https://velog.io/@ayoung0073/DataJpaTest

 

[SpringBoot] DataJpaTest

JPA에 필요한 클래스들만 로딩이 되어 좀 더 빠르게 테스트를 할 수 있다.

velog.io

참조 : https://webcoding-start.tistory.com/20

 

스프링 부트 테스트 : @DataJpaTest

@DataJpaTest @DataJpaTest 어노테이션은 JPA 관련 테스트 설정만 로드합니다. DataSource의 설정이 정상적인지, JPA를 사용하여 데이터를 제대로 생성, 수정, 삭제하는지 등의 테스트가 가능합니다. 그리고

webcoding-start.tistory.com

 

 

@ExtendWith(MockitoExtension.class)

테스트 클래스가 Mockito를 사용함을 의미함.

쉽게말해 org.mockito 패키지를 사용하겠다는 것이다.

그리고 org.mockito 패키지에 포함 된 애노테이션으로는 

@Mock, @InjectMocks 등등이 있다.

 

해당 애노테이션을 사용하여 Service 계층의 슬라이스 테스트가 가능하다.

 

 

 

 

참조 : https://velog.io/@ayoung0073/DataJpaTest

 

[SpringBoot] DataJpaTest

JPA에 필요한 클래스들만 로딩이 되어 좀 더 빠르게 테스트를 할 수 있다.

velog.io

 

참조 : https://tech.lattechiffon.com/2021/07/03/junit5%EC%99%80-mockito%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-mock-test-java/

 

JUnit5와 Mockito를 이용한 Mock Test (Java) – 라떼쉬폰의 코드 베이커리

JUnit5, Hamcrest 및 Mockito JUnit5: Hamcrest: JUnit의 테스트 작성을 보다 문맥적으로 자연스럽고 우아하게 할 수 있도록 도와주는 Matcher 라이브러리입니다. JUnit5부터는 Hamcrest 관련 라이브러리가 포함되어

tech.lattechiffon.com

 

@Mock (org.mockito.Mock)

껍데기의 가짜 빈을 주입하여 준다.

@MockBean 으로 인한 주입과 비슷해보인다.

해당 애노테이션들이 붙은 필드에 가짜빈이 주입된다는것은 같다.

그러나, @MockBean은 애노테이션이 붙은 객체의 가짜빈을 만들어 ApplicationContext (스프링 컨테이너)에 넣어 스프링이 관리하게끔 하지만, @Mock이 붙은 필드에는 그냥 가짜빈만 주입된다.

즉, @MockBean이 붙는 경우에는 테스트에 스프링 컨테이너까지 모두 띄워져서 해야하는 테스트라는 것이고 ( 예를들면, Controller 테스트이다 왜냐하면 스프링컨테이너까지 모두 뜨고 스프링 관련된 빈들까지 모두 등록이 되야 클라이언트의 요청을 받는 스프링 내부로직들이 돌아갈것이 아니겠는가? )

그런 경우가 아니라면 그냥 다른 빈들은 필요없이 해당 필드만 Bean으로 생성되어 주입되면 되는 테스트인 것이다.

 

 

그렇다면 그냥 new로 그냥 객체 생성해서 하면 되지 않을까? 라는 의문이든다.

그것은 좀더 알아봐야할 사항인것 같다.

참조 : https://m.blog.naver.com/whdgml1996/221826586051

 

[spring boot 04] TDD - @Mock @MockBean 차이

Junit을 이용해서 Test를 하면서 해당 테스트에서만 임시로 만들어 주는 객체를 사용할 때 어떨 경우는 ...

blog.naver.com

 

@InjectMocks (org.mockito)

@Mock 으로 인해 생성되고 주입된 객체를, @InjectMocks 애노테이션이 붙은 필드의 객체에 주입하여 주는것이다.

마치 아래에 상황과 같은 경우일 것이다.

즉, MemberService는 MemberRepository를 주입받아야 하는 빈인 상황이다.

   @ExtendWith(MockitoExtension.class)
	public class MemberServiceMockTest {
   
    :
   
    @Mock
    private MemberRepository memberRepository;

    @InjectMocks
    private MemberService memberService;
    
    :
    
  }

 

 

@WebMvcTest

  • @Controller, @ControllerAdvice, @JsonComponent, Converter/GenericConverter, Filter, WebMvcConfigurer, HandlerMethodArgumentResolver 의 대한 애노테이션이 붙은 클래스들만 빈으로 등록.
    @Component, @Service or @Repository 과 같은 애노테이션이 붙은 클래스들은 빈으로 등록 하지 않음. 
  • Spring Security 및 MockMvc도 자동 구성
  • MockMVC를 보다 세밀하게 제어하려면 @AutoConfigureMockMvc 주석을 사용할 수 있다

쉽게 말해, @SpringBootTest는 앱 자체를 띄워서 모든 빈을 등록하고 테스트를 하는 반면에

@WebMvcTest는 Controller 레벨의 테스트에서 필요한 빈들만 등록하여 준다.

그러므로 테스트가 더 가벼워진다. (그냥 더 빠르게 RUN 되고 그런다는것이다.)

 

 

 

참조 : https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/autoconfigure/web/servlet/WebMvcTest.html

 


 

테스트에 사용 가능한 여러 애노테이션을 나타내는 스프링 문서 : 

https://docs.spring.io/spring-boot/docs/current/reference/html/test-auto-configuration.html#appendix.test-auto-configuration