본문 바로가기

Tech/Spring | SpringBoot

[SpringBoot] JUnit 을 이용한 테스트 코드 작성

반응형

SpringBoot 프로젝트에서 기능들의 유닛테스트를 진행하기 위해서 테스트 코드를 작성하려 한다. 테스트 코드를 작성하기 위해서 JUnit 이라는 테스트 프레임워크를 사용하려고 한다. JUnit 자바 테스트 프레임워크로 다양한 어노테이션과 메서드를 통해서 테스트 코드 작성을 편리하게 해준다.

1. JUnit 이란?

JUnit 이란 자바 프로그래밍 언어용 단위 테스트 프레임워크이다. @Test, @BeforeEach, @AfterEach 같은 어노테이션을 기반으로 테스트를 지원한다. 그리고 단정문 (Assert) 메서드를 통해서 테스트 케이스의 사용자의 기대값에 대한 기능의 수행 결과를 확인할 있다. assert 메서드의 결과는 테스트 케이스의 성공 실패 여부를 반환한다.

 

JUnit 3 모듈로 구성되어 있다. Jupiter, Platform, Vintage 3개의 모듈로 구성되는데, Jupiter TestEngine API 구현체로 JUnit5 를 구현하고 있다. Platform 각종 IDE 에서 Test 실행하기 위해 IDE 와의 연동을 보조하는 역할을 한다. Vintage TestEngine 구현체로 JUnit3, 4 구현하고 있다.

2. JUnit 환경 설정

JUnit SpringBoot 에서 사용하기 위해서는 build.gradle 에서 환경설정을 선행해야 한다.

 

test {
	useJUnitPlatform()
}

dependencies {
    ...
    testImplementataion 'org.springframework.boot:spring-boot-starter-test'
    ...
}

 

build tool gradle 에서 사용할 unit test platform 지정할 수 있는데, 여기서 useJUnitPlatform() 으로 JUnit 라이브러리를 지정해준다. 그리고 JUnit 사용하기 위한 dependency 추가한다. SpringBoot 에서는 spring-boot-starter-test 라이브러리에 JUit 포함하고 있기 때문에 해당 라이브러리의 의존성을 추가하면 된다.

3. JUnit 어노테이션

JUnit Life Cycle

JUnit 어노테이션 기반의 프레임워크로 테스트 클래스의 메서드에 붙어있는 어노테이션에 따라서 실행 순서가 결정된다.

 

@Test 테스트용 메서드를 표현하는 어노테이션
@BeforeEach 테스트 메서드의 실행 전에 선행되는 메서드의 어노테이션
@AfterEach 테스트 메서드의 실행 후에 실행되는 메서드의 어노테이션
@BeforeAll 테스트 시작 전에 실행되어야 하는 메서드의 어노테이션.
Static
메서드에만 표시할 있다.
@AfterAll 테스트 종료 후에 실행되어야 하는 메서드의 어노테이션.
Static
메서드에만 표시할 있다.

JUnit 테스트 환경 설정 어노테이션

@SpringBootTest

SpringBoot 에서 통합 테스트를 위해 주로 사용하는 어노테이션이다.

SpringBoot application 실행헀을 때와 같이 @SpringBootApplication 찾아가 하위의 Bean 스캔하여 ApplicationContext 모든 Bean 등록한다. (ComponentScan) 후에 테스트용 Application Context 만들어서 Bean 추가하고, MockBean 찾아서 교체한다.

@DataJpaTest

ApplicationContext  JPA  필요한 설정들만 등록한다. 기본적으로 in-memory embedded 저장소를 사용한다. ComponentScan  하지 않기 때문에 컨테이너의 @Component  지정된 Bean 들이 자동으로 등록되지 않는다.

 

@SpringBootTest  @Component 어노테이션이 붙은 클래스를 테스트하는 경우에 사용한다. 반면에 @DataJpaTest  그렇지 않는 경우 @Repository 등에 대해서 테스트할  사용한다.

ApplicationContext  모든 Bean 들이 등록되지 않기 때문에 테스트 속도가 @SpringBootTest 보다 빠르다.

@WebMvcTest(class)

Class 명으로 할당된 클래스만 실제로 로드하여 테스트를 수행한다.

매개변수를 지정해주지 않으면 @Controller, @RestController, @RestControllerAdvice  컨트롤러와 관련된 Bean  모두 로드된다. 스프링의 모든 Bean  로드하는 @SpringBootTest 대신에 컨트롤러 관련 코드만 테스트 하는 경우에 사용한다.

@ExtendWIth

JUnit4 에서 @RunWith 으로 사용되던 어노테이션의 변경된 버전이다.

@ExtendWIth 사용하여 메인으로 실행될 클래스를 지정할 있다.

@SpringBootTest 기본적으로 @ExtendWith 포함하고 있다.

@Autowired

@Autowired 어노테이션은 기본 SpringBoot application 에서 사용되는 것과 같이 등록된 Bean 에서 해당 타입의 Bean 을 찾아서 주입해주고 이를 테스트에 사용할 수 있도록 해준다.

 

만약 MockMvc 타입으로 선언된 컨트롤러의 API 테스트하는 용도인 MockMvc 객체를 주입 받는다. perform(), andExpect(), andDo(), andReturn() 등의 메서드를 활용하여 컨트롤러에 요청을 보내고 응답에 대한 테스트를 수행할 수 있다.

@MockBean

테스트할 클래스에서 주입받고 있는 객체에 대해 가짜 객체를 생성해주는 어노테이션이다.

해당 객체는 실제 동작을 하지는 않는다. 대신 given() 메서드를 활용하여 가짜 객체의 동작에 대해 정의하여 사용할 있다.

@AutoConfigureMockMvc

spring.test.mockmvc 설정을 로드하면서 MockMvc 의존성을 자동으로 주입한다.

MockMvc 클래스는 REST API 테스트를 있는 클래스이다.

@Import

필요한 Class 들을 Configuration 으로 만들어 사용할 있다. Configuration Component 클래스도 의존성을 설정할 있다. Import 클래스는 주입으로 사용할 있다.

@TestPropertySource

테스트 환경에서 사용할 환경 설정을 따로 설정하고 로드할 사용한다.

@TestPropertySource("classpath:appliaction-test.properties") 같은 형식으로 사용하여 해당 프로젝트의 classpath 에서 주어진 이름의 설정 파일을 찾아서 환경 설정을 한다. 예시의 경우 application-test.properties 사용하여 테스트를 수행한다.

4. 테스트 코드 구현

@SpringBootTest
@TestPropertySource("classpath:application-test.properties")
public class TestServiceTest {

    @Autowired
    TestService testService;

    @BeforeEach
    void setup() {
        System.out.println("setup before each test");
    }

    @AfterEach
    void tearDown() {
        System.out.println("tear down after each test");
    }

    @BeforeAll
    static void setupAll() {
        System.out.println("setup before all test");
    }

    @AfterAll
    static void tearDownAll() {
        System.out.println("tear down after all test");
    }

    @Test
    void testHello() {
        String hello = testService.helloTest();
        assertEquals("Hello Test", hello);
    }

    @Test
    void testTest() {
        assertEquals(1 + 1, 2);
    }
}

 

위의 예제는 testHello() testTest() 두개의 테스트 케이스에 대해서 테스트를 수행하는 코드이다.

두개의 테스트 케이스에는 @Test 어노테이션을 붙여서 테스트 케이스로 지정하고 각각의 메서드에서 assert 메서드를 사용해서 테스트를 수행한다.

 

예제에서는 @SpringBootTest 어노테이션과 @TestPropertySource 두개의 어노테이션을 통해서 테스트 환경 설정한다. @SpringBootTest 통해서 실제 SpringBoot 실행환경과 같이 ApplicationContext Bean 등록하여 테스트에 사용한다. 예제에서는 @Autowired 지정된 testService TestService 주입되어 사용된다. @TestPropertySource 에서는 classpath 있는 application-test.properties 파일로 실행 환경을 설정한다.

 

테스트 케이스 수행 전후에 실행하기위해 @BeforeAll, @AfterAll, @BeforeEach, @AfterEach 붙은 메서드들이 구현되어 있다. @BeforeAll @AfterAll 전체 테스트가 실행되기 전후에 한번씩, @BeforeEach @AfterEach 테스트 케이스 전후에 실행된다. @BeforeAll @AfterAll 지정되는 메서드들은 기본적으로 static 으로 선언되어야 한다.

[Reference]

- https://jungguji.github.io/2020/07/05/H2-DB%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-Repository-Test/

 

H2 DB를 이용한 Repository Test

상황프로덕션 환경에서 Mariadb를 활용하고 있었는데, 프로덕션 환경의 DB로 Repository class를 테스트를 진행하니 테스트 데이터는 롤백되어 DB 남지 않았지만, Auto increment로 지정한 ID가 증가돼서 실

jungguji.github.io

- https://da-nyee.github.io/posts/spring-springboottest-vs-datajpatest/

 

[Spring] @SpringBootTest vs @DataJpaTest

@SpringBootTest

da-nyee.github.io

- https://thalals.tistory.com/273

 

[Spring boot] 테스트 코드 작성 (1) - Junit을 이용한 Unit Test(단위 테스트) / Assert 메소드

Spring 테스트 코드 작성해보기! 목차 Junit 이란 Junit 사용설정 Junit 어노테이션 Junit 사용법 Assert 메소드 @Nest사용 엣지 케이스 확인 Junit을 이용한 단위테스트 1) 단위 테스트란 프로그램을 작은 단

thalals.tistory.com

- https://smpark1020.tistory.com/163

 

테스트할 때 MockMvc 주입받는 방법

JUnit으로 테스트 코드를 작성할 때 MockMvc를 많이 사용하게 된다. MockMvc를 주입받는 방법은 2가지가 있다. @WebMvcTest 사용 @WebMvcTest를 사용하면 컨트롤러 클래스를 주입받을 수 있다. 단, 서비스나

smpark1020.tistory.com

 

반응형