본문 바로가기

Backend/Spring

Spring Boot Controller Test

What You Will Build

Application Context가 로드하는 것을 테스트한다.

Spring의 MockMvc를 사용해 web layer를 테스트한다.

Run the Application

package com.example.testingweb;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TestingWebApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestingWebApplication.class, args);
    }
}

@SpringBootApplication is a convenience annotation that adds all of the following:

  • @Configuration: Tags the class as a source of bean definitions for the application context.
  • @EnableAutoConfiguration: Tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings.
  • @EnableWebMvc: Flags the application as a web application and activates key behaviors, such as setting up a DispatcherServlet. Spring Boot adds it automatically when it sees spring-webmvc on the classpath.
  • @ComponentScan: Tells Spring to look for other components, configurations, and services in the the com.example.testingweb package, letting it find the HelloController class.

Test the Application

Sanity Check Test

Application Context가 시작하지 않으면 fail하는 테스트이다.

package com.example.testingweb;

import org.junit.jupiter.api.Test;

import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class TestingWebApplicationTests {

    @Test
    public void contextLoads() {
    }

}

@SpringBootTest어노테이션은 스프링 부트가 main configuration class(@SpringBootApplication 어노테이션이 붙은 클래스)를 찾도록 하고, 그 클래스로 Spring application context를 시작시킨다.

테스트는 IDE로 실행시킬 수 있고 ./mvnw testor ./gradlew test 명령어로 command line으로 실행시킬 수 있다.

context가 application을 만들고 있는지 확인하기 위해, 다음과 같이 assertion을 추가할 수 있다.

package com.example.testingweb;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class SmokeTest {

    @Autowired
    private HomeController controller;

    @Test
    public void contextLoads() throws Exception {
        assertThat(controller).isNotNull();
    }
}

스프링은 @Autowired 어노테이션을 해석하여 controller가 테스트 메소드가 돌기 전에 주입되도록 한다.

Assert the Behavior of the Application

  1. 어플리케이션을 시작한다.
  2. 커넥션을 리슨한다.
  3. HTTP Request를 전송하고 Response를 Assert한다.
package com.example.testingweb;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class HttpRequestTest {

    @LocalServerPort
    private int port;

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void greetingShouldReturnDefaultMessage() throws Exception {
        assertThat(this.restTemplate.getForObject("http://localhost:" + port + "/",
                String.class)).contains("Hello, World");
    }
}

webEnvironment=RANDOM_PORT로 서버를 랜덤 포트로시작하고 @LocalServerPort로 포트를 주입한다.

Test Below the Server Using MockMVC And @AutoConfigureMockMvc

package com.example.testingweb;

import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;

@SpringBootTest
@AutoConfigureMockMvc
public class TestingWebApplicationTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void shouldReturnDefaultMessage() throws Exception {
        this.mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
                .andExpect(content().string(containsString("Hello, World")));
    }
}

In this test, the full Spring application context is started but without the server.

Test Only the Web Layer Using @WebMvcTest

@WebMvcTest
public class WebLayerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void shouldReturnDefaultMessage() throws Exception {
        this.mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
                .andExpect(content().string(containsString("Hello, World")));
    }
}

스프링 부트는 전체 context를 초기화 하지 않고 web layer만 초기화 한다.

Test Just One Controller

@WebMvcTest(HomeController.class)를 사용해 하나의 컨트롤러만 테스트한다.

@MockBean 으로 service layer를 mock하여 inject한다.

'Backend > Spring' 카테고리의 다른 글

@Transactional 전파 전략  (0) 2023.05.07
DI와 IoC  (0) 2023.04.07
Spring Container와 Bean의 Lifecycle  (0) 2023.04.07
Spring Session With Redis 설정하기  (0) 2023.03.09
SpringFox 3.0.0 Server URL Error  (0) 2023.03.03