티스토리 뷰

목차

1. 단위 테스트와 통합 테스트

2. JUnit 5

3. IntelliJ 에서 JUnit 5를 이용한 테스트

4. @ExtendWith(SpringExtension.class)

5. Spring Boot Slice Test

6. 테스트 전략

 

 

 

1. 단위 테스트와 통합 테스트

1) 단위테스트

모듈들이 각각 정상적으로 작동하는지 테스트 한다.

테스트의 단위를 클래스로 잡는다면 대상 클래스의 기능이 정상적으로 작동하는지 확인하는 작업이다.
따라서 동작하는데 필요한 협력 클래스(외부 라이브러리)의 객체는 mock(가짜) 객체로 만들어 복잡도를 낮추고

대상 클래스의 테스트에 집중하도록 한다.

이 때 사용하는 Java mocking framework 중 하나로 Mockito 가 있다.

Mockito 사용법 참고

 

2) 통합테스트

단위 테스트에서 모듈 단위로 테스트를 완료하면 모든 클래스가 협력 클래스의 실제 객체와 의존관계를 맺고

애플리케이션이 정상적으로 작동하는지 확인하는 작업이다.

테스트의 복잡도가 높아 에러를 찾는 과정이 어려울 수 있다.

 

2. JUnit 5

자바 애플리케이션을 단위 테스트 할 때 사용하는 프레임워크 중 JUnit 이 있고 최신 버전이 JUnit 5이다.

JUnit 5는 이전 버전과 다르게 다음과 같은 구조로 이루어져 있다.

JUnit Platform + JUnit Jupiter + JUnit Vintage

JUnit Platform
JUnit Platform은 JVM에서 테스트 프레임워크를 실행하는데 기초를 제공한다. 또한 TestEngine API를 제공해 테스트 프레임워크를 개발할 수 있다.

JUnit Jupiter
JUnit Jupiter는 JUnit 5에서 테스트를 작성하고 확장을 하기 위한 새로운 프로그래밍 모델과 확장 모델의 조합이다.

JUnit Vintage
JUnit Vintage는 하위 호환성을 위해 JUnit3과 JUnt4를 기반으로 돌아가는 플랫폼에 테스트 엔진을 제공해준다.

 

JUnit 5 사용법 참고

 

 

3. IntelliJ 에서 JUnit 5를 이용한 테스트

spring initializr 에서 Spring Boot 프로젝트를 만들면 다음과 같이 테스트용 Spring Boot Starter 라이브러리를 dependency로 추가한다.

testImplementation 'org.springframework.boot:spring-boot-starter-test'

 

여기에 JUnit5, Mockito, Hamcrest 등의 패키지가 포함되어 있어 별도로 dependency에 추가하지 않아도 사용할 수 있다.

 

만든 프로젝트를 JUnit 5 를 지원하는 버전의 IntelliJ 에서 열고 테스트 클래스를 만든다.

테스트 대상 클래스명에서 단축키 Ctrl + Shift + T 를 이용해 만들 수 있다.

여기서 Testing library 가 자동으로 JUnit 5로 설정되어 있는 걸 확인할 수 있다.

JUnit 5 는 @Test 어노테이션을 이용해 테스트 메소드인지 확인하기 때문에 다음과 같이 메소드 위에 붙여주고

JUnit Jupiter Assertions 의 api를 이용해 테스트 한다. 

Assertions static import 단축키는 Alt(cmd) + Enter

 

test() 메소드를 실행하면 JUnit 이 테스트를 진행한다.

테스트가 끝나면 다음과 같이 결과를 확인할 수 있다.

 

 

4. @ExtendWith(SpringExtension.class)

@ExtendWith는 junit 테스트 컨텍스트 프레임워크의 확장 클래스를 지정할 때 사용한다.

JUnit 이 테스트를 진행할 때 사용할 확장 기능을 클래스, 메소드 등에 적용할 수 있는 어노테이션이다.

확장 클래스를 SpringExtension.class로 설정하면 junit이 테스트를 진행하는 중에 Spring이 Applicationcontext 를 만들고 관리해준다.

public class AppTest {
    @Autowired ApplicationContext context;

    @Test
    void test() {
        assert context != null;

        String[] beans = context.getBeanDefinitionNames();
        System.out.println("count = " + context.getBeanDefinitionCount());
        Arrays.asList(beans).forEach(b -> System.out.println("bean = " + b));
    }
}

@ExtendWith(SpringExtension.class) 를 붙이지 않으면 ApplicationContext 는 만들어지지 않고 다음과 같이 null 로 확인된다.

@ExtendWith(SpringExtension.class) 를 붙이고 확인해보면 ApplicationContext 가 만들어 졌고 8개의 bean을 등록해 관리하는 것을 확인할 수 있다.

 

Spring 은 하나의 ApplicationContext를 만들어 테스트 클래스 내 모든 메소드에서 공유한다.

또한 ApplicationContext 를 @Autowired로 주입받을 수 있는 이유는 스프링 애플리케이션 컨텍스트를 초기화할 때 자기 자신도 빈으로 등록하기 떄문이다.

 

5. Spring Boot Slice Test

Spring Boot는 단위 테스트와 통합 테스트의 중간 쯤에 해당하는 Slice Test를 할 때 어노테이션으로 간편하게 설정할 수 있도록 지원한다. Test Auto-configuration Annotations 참고

 

1) @DataJpaTest : jpa를 사용하는 repository를 빈으로 만들어 주입해주고 이 외에 @Component 가 붙은 다른 클래스(@Controller, @Service, JPA를 사용하지 않는 @Repository)는 무시한다. 데이터베이스 연결과 JPA를 활용한 생성,수정,삭제,조회 기능을 테스트 할 때 사용한다.

 

2) @WebMvcTest : @Controller, @ControllerAdvice, @JsonComponent, Converter, GenericConverter, Filter 등을 스캔해 웹과 관련해 요청/응답 테스트를 할 때 사용한다.

 

@WebMvcTest 어노테이션을 사용해 가짜 요청(MockMvc 사용)을 dispatcherServlet 에게 보내고 응답을 확인하는 테스트를 할 때 @Service, @Repository 어노테이션이 붙은 클래스는 bean생성 대상에서 제외하지만

dispatcherServlet, webConfig, requestMappingHandlerMapping, mvcValidator 등 웹과 관련된 bean들을 컨텍스트에 등록하고 서로 조합이 된 상태로 동작하는 테스트이기 때문에 단위테스트 보다는 큰 단위라고 할 수 있다.


이렇게 특정 계층을 테스트 하기 위해 필요한 일부 bean 들만 등록하고 사용하기 때문에 통합 테스트에 비해 속도가 향상되고 재사용성을 높일 수 있다.

 

@SpringBootTest 는 실제 애플리케이션을 구동하기 때문에 필요한 모든 bean 을 로드한다.

애플리케이션의 규모가 클 수록 Slice Test 에서 사용하는 어노테이션과의 속도 차이 또한 클 것이다.


Slice Test 각 어노테이션들은 다음과 같이 @ExtendWith(SpringExtension.class) 를 사용하기 때문에 테스트를 진행할 때 Spring이 ApplicationContext를 만들고 관리한다.

@WebMvcTest(SupplementCategoryController.class)
public class AppTest {
    @Autowired ApplicationContext context;

    @Autowired MockMvc mockMvc;
    @MockBean SupplementCategoryService categoryService;
    @Autowired SupplementCategoryController controller = new SupplementCategoryController(categoryService);

    @Test
    void test() {
        assert context != null;

        String[] beans = context.getBeanDefinitionNames();
        System.out.println("count = " + context.getBeanDefinitionCount());
        Arrays.asList(beans).forEach(b -> System.out.println("bean = " + b));
    }
}

 

Spring Boot Slice Test는 웹과 관련된 테스트를 할 때 필요한 설정을 autoconfigure 패키지들을 import 하는 방식으로 지원하고 있으며 @WebMvcTest 는 다음과 같다.

목록중에 org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration 클래스를 통해

package org.springframework.boot.autoconfigure.web.servlet 클래스를 확인해 보면

DispatcherServlet 빈을 스프링 컨테이너에 하는 걸 볼 수 있다.

 

Spring boot가 Configuration 관련 어노테이션을 사용해 동작하는 위의 내용은 정확하지 않기 때문에, Spring Boot autoconfiguration을 공부하고 수정할 예정.

 

 

6. 테스트 전략

1) null 값 처리를 포함한 도메인 객체 테스트

2) 가짜 협력자를 활용해서 모든 비즈니스 로직을 검사하는 서비스 계층 테스트 

3) Slice Test

4) 통합 테스트

 

 

 

728x90