MockMvc를 SpringBootTest와 함께 사용하는 것과 WebMvcTest를 사용하는 것의 차이점


95

저는 Spring Boot를 처음 사용하고 SpringBoot에서 테스트가 어떻게 작동하는지 이해하려고합니다. 다음 두 코드 스 니펫의 차이점이 무엇인지 약간 혼란 스럽습니다.

코드 스 니펫 1 :

@RunWith(SpringRunner.class)
@WebMvcTest(HelloController.class)
public class HelloControllerApplicationTest {
    @Autowired    
    private MockMvc mvc;

    @Test
    public void getHello() throws Exception {
        mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(content().string(equalTo("Greetings from Spring Boot!")));
    }
}

이 테스트는 @WebMvcTest기능 슬라이스 테스트를위한 주석을 사용 하며 웹 애플리케이션의 MVC 레이어 만 테스트합니다.

코드 조각 2 :

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class HelloControllerTest {

    @Autowired
    private MockMvc mvc;

    @Test
    public void getHello() throws Exception {
    mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andExpect(content().string(equalTo("Greetings from Spring Boot!")));
    }
}

이 테스트는 @SpringBootTest주석과 MockMvc. 그렇다면 이것이 코드 조각 1과 어떻게 다른가요? 이것이 다른 점은 무엇입니까?

편집 : 코드 조각 3 추가 (Spring 문서에서 통합 테스트의 예로 찾았습니다)

@RunWith(SpringRunner.class) 
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 
public class HelloControllerIT {
    
    @LocalServerPort private int port;
    private URL base;
    
    @Autowired private TestRestTemplate template;
    
    @Before public void setUp() throws Exception {
        this.base = new URL("http://localhost:" + port + "/");
    }
    
    @Test public void getHello() throws Exception {
        ResponseEntity < String > response = template.getForEntity(base.toString(), String.class);
        assertThat(response.getBody(), equalTo("Greetings from Spring Boot!"));
    }
}

답변:


88

@SpringBootTest일반적인 테스트 주석입니다. 1.4 이전에 동일한 작업을 수행하는 것을 찾고 있다면 사용해야합니다. 슬라이싱 을 전혀 사용하지 않으므로 전체 애플리케이션 컨텍스트를 시작하고 구성 요소 스캔을 전혀 사용자 정의하지 않습니다.

@WebMvcTest정의한 컨트롤러와 MVC 인프라 만 스캔합니다. 그게 다야. 따라서 컨트롤러가 서비스 계층의 다른 Bean에 대한 종속성이있는 경우 해당 구성을 직접로드하거나 모의 파일을 제공 할 때까지 테스트가 시작되지 않습니다. 앱의 아주 작은 부분 만로드하므로 훨씬 빠릅니다. 이 주석은 슬라이싱을 사용합니다.

문서를 읽는 것도 도움이 될 것입니다.


응답 해주셔서 감사합니다 !!. 따라서 내가 올바르게 이해한다면 두 코드 조각이 모두 응용 프로그램의 MVC 부분 만 테스트한다는 의미입니다. 그러나 tcode 스 니펫 1은 전체 애플리케이션 컨텍스트를로드하는 반면 코드 스 니펫 2는 컨트롤러 만 스캔합니다. 이 올바른지? 코드 조각 1을 컨트롤러 테스트를위한 단위 테스트로 간주 할 수 있습니까?
Revansha

1
아니요, 정확하지 않습니다. SpringBootTest전체 앱을로드하는 것입니다 (일부 확장하려면 기본적으로 사용 가능한 컨테이너가있는 경우 포함 된 컨테이너를 시작하지 않습니다. 그것이 바로 그 이유 webEnvironment입니다). 나는 그것이 @SpringBootTest컨트롤러의 단위 테스트 라고 말하지 는 않지만 실제로는 통합 테스트입니다. WebMvcTest의존성이있는 경우 직접 제공해야한다는 점에서 컨트롤러의 단위 테스트입니다 (구성 또는 일종의 모의).
스테판 니콜

응답 해 주셔서 다시 한 번 감사드립니다. 질문을 수정하고 코드 스 니펫 3을 추가했습니다. @SpringBootTest 주석이 통합 테스트에 더 많이 사용된다고 언급했습니다. Snippet 3이이를 증명한다고 생각합니다. 그렇다면 통합 테스트가 Snippet 3 에서처럼 수행된다면 Snippet 2는 무엇을할까요? Snippet 2는 SpringBootTest 주석과 모의 환경 (wenEnvironment 속성의 기본값)을 사용합니다. 또한 스 니펫 3은 임베디드 서버를 시작하고 실제로 HTTP 호출을 수행하는 반면 스 니펫 2는이를 수행하지 않습니다. 그래서 이것을 고려하면, 스 니펫 2는 단위 테스트로 간주되지 않습니까?
Revansha

4
나는 우리가 여기서 이것을 분류 할 것인지 잘 모르겠습니다. 어쩌면 반짝 반짝? 당신이 항상 그리워하는 것하는 것은이라는 애플리케이션 컨텍스트 그 SpringBootTestWebMvcTest생성 크게 다르다. 전자는 전체 앱을로드하고 모든 자동 구성을 활성화하는 반면 후자는 Spring Mvc 만 활성화하고 HelloController. 결국 단위 테스트가 의미하는 바에 따라 다릅니다. 그러나 그것이 차이입니다.
Stephane Nicoll

응답 해 주셔서 감사합니다. 그것은 저에게 매우 도움이됩니다. 이제 내 테스트가 SpringBootTest로 실행될 수 있지만 WebMvcTest에서 예외가 발생하는 이유를 이해합니다. 다시 한번 감사드립니다.
Alps1992

69

@SpringBootTest 주석은 Spring Boot에게 기본 구성 클래스 (예 : @SpringBootApplication이있는 클래스)를 찾아서 Spring 애플리케이션 컨텍스트를 시작하는 데 사용하도록 지시합니다. SpringBootTest는 완전한 애플리케이션을로드하고 느릴 수있는 모든 빈을 주입합니다.

@WebMvcTest- 컨트롤러 계층을 테스트하기 위해 모의 개체를 사용하여 필요한 나머지 종속성을 제공해야합니다.

아래에 몇 가지 주석이 더 있습니다.

응용 프로그램 슬라이스 테스트 전체 응용 프로그램을 자동 구성하는 대신 응용 프로그램의 간단한 "슬라이스"를 테스트하고 싶을 때가 있습니다. Spring Boot 1.4에는 4 개의 새로운 테스트 주석이 도입되었습니다.

@WebMvcTest - for testing the controller layer
@JsonTest - for testing the JSON marshalling and unmarshalling
@DataJpaTest - for testing the repository layer
@RestClientTests - for testing REST clients

자세한 내용은 https://spring.io/guides/gs/testing-web/ 을 참조하십시오.


다음은 Sping Boot Reference-Test Auto-configuration Annotations 링크 입니다. 여기에는 @ roshankumar-mutha가 4 개 이상 나열했습니다. 시작 안내서에 대한 링크는 이러한 조각을 자세히 다루지 않습니다.
George Pantazes

15

MVC 테스트는 애플리케이션의 컨트롤러 부분만을 다루기위한 것입니다. HTTP 요청 및 응답은 모의 처리되므로 실제 연결이 생성되지 않습니다. 반면을 사용 @SpringBootTest하면 웹 애플리케이션 컨텍스트에 대한 모든 구성이로드되고 연결이 실제 웹 서버를 통해 진행됩니다. 이 경우 MockMvc빈을 사용하지 않고 RestTemplate대신 표준 (또는 새로운 대안 TestRestTemplate)을 사용합니다.

그렇다면 언제 둘 중 하나를 선택해야합니까? @WebMvcTest서버 측에서 컨트롤러를 통합 테스트하기위한 것입니다. @SpringBootTest반면에 클라이언트 측에서 애플리케이션과 상호 작용하려는 경우 통합 테스트에 사용해야합니다.

그렇다고해서 mock을 사용할 수 없다는 의미는 아닙니다 @SpringBootTest. 통합 테스트를 작성하는 경우 여전히 필요할 수 있습니다. 어쨌든 간단한 컨트롤러의 단위 테스트에만 사용하지 않는 것이 좋습니다.

source-Spring Boot로 마이크로 서비스 학습


1
이 대답이 upvoted 왜 당신이 사용하는 경우 난 .. 이해하지 못하는 @SpringBootTest진짜 웹 서버는 또한이 없으면 시작되지, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT(나 DEFINED_PORT)와 연결은 실제 웹 서버를 통해 이동하지 않습니다. 의 기본값은 @SpringBootTest입니다 WebEnvironment.MOCK.
Koray Tugay
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.