source

Spring Boot 1.4 MVC 테스트에서 @WebMvcTest로 MockMvc 설정

manycodes 2023. 9. 13. 22:50
반응형

Spring Boot 1.4 MVC 테스트에서 @WebMvcTest로 MockMvc 설정

설정할 작업 코드가 거의 없습니다.MockMVc새로운 Spring Boot 1.4로 다양한 방법으로@WebMvcTest. 독립형 설치 방법은 잘 알고 있습니다.내가 알고 싶은 것은 셋업의 차이점입니다.MockMvc통해.WebApplicationContext자동배선으로MockMvc.

Code Snippet 1 : Web Application Context Setup을 통한 Mock

@RunWith(SpringRunner.class)
@WebMvcTest(controllers = ProductController.class)
public class ProductControllerTest {

private MockMvc mockMvc;

@Autowired
private WebApplicationContext webApplicationContext;

@MockBean
private ProductService productServiceMock;

@Before
public void setUp() {
     mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}

@Test
public void testShowProduct() throws Exception {      

    Product product1 = new Product();
    /*Code to initialize product1*/

    when(productServiceMock.getProductById(1)).thenReturn(product1);

    MvcResult result = mockMvc.perform(get("/product/{id}/", 1))
            .andExpect(status().isOk())
            /*Other expectations*/
            .andReturn();
  }
}

에 의거하여WebMvcTestAPI 설명서, 기본적으로 @WebMvcTest 주석이 달린 테스트는 Spring Security와 MockMvc도 자동으로 구성됩니다. 그래서 여기 401 Unauthorized 상태 코드를 기대했는데 테스트는 200 상태 코드로 통과됩니다.

다음으로 오토 배선을 해봤습니다.MockMvc, 추가하지 않으면 401 Unauthorized status code로 테스트가 실패합니다.@AutoConfigureMockMvc(secure=false)아니면 업데이트.@WebMvcTest보안을 비활성화하기 위한 주석:

@WebMvcTest(controllers = IndexController.class, secure = false)


다음은 보안을 명시적으로 비활성화한 후에만 통과하는 코드입니다.

코드 스니펫 2: 자동배선을 통한 MockMvc

@RunWith(SpringRunner.class)
@WebMvcTest(controllers = ProductController.class)
@AutoConfigureMockMvc(secure=false)
public class ProductControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
@MockBean
private ProductService productServiceMock;

@Test
public void testShowProduct() throws Exception {      

    Product product1 = new Product();
    /*Code to initialize product1*/

    when(productServiceMock.getProductById(1)).thenReturn(product1);

    MvcResult result = mockMvc.perform(get("/product/{id}/", 1))
            .andExpect(status().isOk())
            /*Other expectations*/
            .andReturn();
  }
}

그래서 제 질문은 다음과 같습니다.

  1. 코드 조각 1이 자동 배선 중 401 무단 상태 코드 오류를 보고하지 않은 이유MockMvc했습니다. 또한 공식 문서에서 말하는 내용을 반복합니다. 기본적으로 @WebMvcTest 주석이 달린 테스트는 Spring Security와 MockMvc도 자동으로 구성됩니다. 하지만 이 경우에는 나타납니다.@WebMvcTest는 Spring Security 자동 구성과는 무관합니다(코드 스니펫 1이 401 오류 없이 통과되기 때문입니다).결국 제가 어떻게 설정하느냐에 달려있습니다.MockMvc. 여기가 맞나요?

  2. 두 접근 방식의 차이점/목표는 무엇입니까?

  3. 보안을 해제하는 방법은 다음과 같습니다.@AutoConfigureMockMvc(secure=false)하는 것과 하는 것이 다릅니다@WebMvcTest(controllers = IndexController.class, secure = false). 어떤 접근 방식이 선호되거나 언제(또는 어디에서) 사용할 것입니까?

저도 비슷한 문제를 접하게 되었습니다.@WebMvcTestauto는 기본 auth로 Spring Security를 구성하지만 나는WebSecurityConfig확장되는 클래스WebSecurityConfigurerAdapter.이 클래스에서 기본 인증을 비활성화하고 토큰 기반 보안을 구성했습니다.그 말은WebSecurityConfigclass는 Spring Security를 구성하는 데 사용되지 않습니다.

그 문제를 해결하기 위해, 나는 덧붙였습니다.@ContextConfiguration내 유닛 테스트 클래스에 그리고 의존성의 모의를 추가했습니다.WebSecurityConfig학급.

@RunWith(SpringRunner.class)
@WebMvcTest(controllers = CategoryRestService.class)
@ContextConfiguration(classes = {MjApplication.class, WebSecurityConfig.class})
public class CategoryRestServiceTest {
    
    @MockBean
    private CategoryRepository repository;
    
    @MockBean
    CurrentUserDetailsService currentUserDetailsService;
    
    @MockBean
    TokenAuthProvider tokenAuthProvider;
    
    @Autowired
    MockMvc mockMvc;
    
    private MediaType contentType = new    MediaType(MediaType.APPLICATION_JSON.getType(),
            MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));
    
    
    @Test
    public void getCategories() throws Exception {
        Category category1 = new Category();
        category1.setName("Test Category 1");
        category1.setId(1L);
        Category category2 = new Category();
        category2.setName("Test Category 2");
        category2.setId(2L);
        List<Category> categoryList = new ArrayList<Category>();
        categoryList.add(category1);
        categoryList.add(category2);
        given(this.repository.findAll())
        .willReturn(categoryList);
        mockMvc.perform(get("/public/rest/category"))
        .andExpect(status().isOk())
        .andExpect(content().contentType(contentType))
        .andExpect(jsonPath("$[0].id", is(1)))
        .andExpect(jsonPath("$[0].name", is("Test Category 1")))
        .andExpect(jsonPath("$[1].id", is(2)))
        .andExpect(jsonPath("$[1].name", is("Test Category 2")));
    }

}

github의 이 문제에 의하면

https://github.com/spring-projects/spring-boot/issues/5476

@WebMvcTest 자동 구성 기본값, spring-security-test가 클래스 경로에 있을 때 기본 인증

질문에 대한 답변:

  1. 코드 스니펫 1에서 테스트 클래스에 MockMvc를 주입하지 않은 경우 설정 방법의 빌드에 .apply(springSecurity())를 추가해야 하므로 spring은 기본 구성(있는 경우 사용자 지정 보안 구성이 아님)을 사용합니다.
  2. 두 접근 방식 모두 기본적으로 동일한 작업을 수행합니다. 차이점은 두 번째는 MockMvc에 이미 기본 인증이 포함되어 있기 때문에 secure=를 사용해야 한다는 것입니다.
  3. 설명서에서:

기본적으로 @WebMvcTest 주석이 달린 테스트는 Spring Security 및 MockMvc도 자동으로 구성됩니다(HtmlUnit WebClient 및 Selenium WebDriver 지원 포함).MockMVC의 보다 세밀한 제어를 위해 @AutoConfigureMockMvc 주석을 사용할 수 있습니다.

이것이 직접적인 관련이 있는 것은 확실하지 않지만 스프링부트를 사용하는 경우에 눈에 띄는 버그가 있습니다.@WebMvcTest의 습관, @EnableWebSecurity됩니다.config가다가 .버그 보고서에는 몇 가지 해결 방법이 언급되어 있습니다.중용:

@WebMvcTest(includeFilters = @Filter(classes = EnableWebSecurity.class))

이것이 올바른 방법인지 아닌지는 모르겠지만 아래와 같은 방법으로 구성 클래스를 비활성화 할 수 있습니다.

@WebMvcTest(ProductController.class)
@ContextConfiguration(classes = ProductController.class)
public class ProductControllerTest {
  @Autowired
  private MockMvc mockMvc;

  @MockBean
  private ProductService productServiceMock;

언급URL : https://stackoverflow.com/questions/38168163/setting-up-mockmvc-with-webmvctest-in-spring-boot-1-4-mvc-testing

반응형