source

MockMVC를 사용한 통합 테스트 스프링 부트

manycodes 2023. 7. 30. 17:57
반응형

MockMVC를 사용한 통합 테스트 스프링 부트

MockMvc에서 Spring Boot 응용 프로그램을 테스트하는 데 문제가 있습니다.

저는 다음과 같은 시험 수업이 있습니다.

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {SpringConfiguration.class, SecurityConfiguration.class})
@IntegrationTest({"server.port=8080"})
@WebAppConfiguration
public class DemoTest {

@Autowired
private EmbeddedWebApplicationContext webApplicationContext;

private MockMvc mockMvc;

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

@Test
public void testGetAccountUnauthenticated() throws Exception {
    mockMvc.perform(get("/accounts/1").accept(MediaType.APPLICATION_JSON))
            .andExpect(status().isUnauthorized());
}
}

이렇게 하면 401이 아닌 HTTP 200이 됩니다.구성 요소 검색 및 자동 구성이 활성화되어 있으며 보안 구성 클래스에서 스프링 보안이 다음과 같이 구성되어 있습니다.

@Configuration
@EnableWebSecurity
@EnableWebMvcSecurity // required for use of @AuthenticationPrincipal in MVC controllers.
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
public void configure(WebSecurity web) {
    web.debug(true);
}

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    //set up authentication.
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().anyRequest().authenticated();
   // set up form login
}
}

하여 RestTemplate에 http://localhost:8080/accounts/1그러면 예상되는 동작을 받습니다(HTTP 401).

자동 배선을 제안하는 다른 예(예: 테스트를 위한 Spring Boot 설정 보안)를 보았습니다.FilterChainProxy합니다.WebApplicationContext.addFilters(filterChainProxy)사실 실패합니다.org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.security.web.FilterChainProxy] found).

두 가지 질문이 있습니다.

  1. 주입된 WebApplicationContext에서 SpringSecurity 필터를 자동으로 사용하지 않는 이유는 무엇입니까?FilterChainProxy를 가져와 수동으로 추가할 수 있더라도 JavaDoc for EmbeddedWebApplicationContext는 다음과 같이 말합니다.

컨텍스트에 정의된 모든 {@linkServlet} 또는 {@linkFilter} 빈이 내장된 Servlet 컨테이너에 자동으로 등록됩니다.

따라서 보안 필터 체인을 수동으로 추가할 필요가 없습니다(잘못되었습니까?).Spring Boot의 자동 구성 마법으로 인해 이것이 "그냥 작동할 것"이라고 예상하십니까?

  1. 응용 프로그램 컨텍스트에 FilterChainProxy가 없는 이유는 무엇입니까?다시 말씀드리지만, 자동 구성에 대한 제 예상이 틀릴 수도 있습니다. 하지만 저는 자동 구성이 컨텍스트 구성의 일부로 구성될 것이라고 생각했습니다.

조언을 해주셔서 미리 감사드립니다.


편집

  • FilterChainProxy가 주입되지 않는 이유는 구성이 다음으로 설정되어 있기 때문입니다.

    public void 구성(WebSecurity Web) {web.debug(true); }

이은실구다니합을 합니다.org.springframework.security.web.debug.DebugFilter대신..

@Resource(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
private Filter securityFilter;

MockMvcBuilder에 다음과 같이 추가하면 다음과 같습니다.

MockMvcBuilders.webAppContextSetup(webApplicationContext).addFilters(securityFilter)

그러면 예상대로 작동합니다.

하지만 테스트 결과에 영향을 미칠 수 있는 필터에서 발생할 수 있는 모든 것이 발생할 수 있기 때문에 MockMVC가 필터를 무시하는 것은 요청을 테스트하는 데 중요한 것 같은데 이해가 되지 않습니다.또한 제대로 테스트하려면 서블릿 컨텍스트에서 모든 필터를 검색하고 우선 순위/url 매핑을 설정하여 적절하게 추가해야 합니다.이는 오류가 발생하기 쉽고 불필요한 것으로 보입니다.

저는 MockMVC가 @dave-syer가 언급한 것처럼 컨트롤러에서 SpringMVC와 사용자 지정 코드를 테스트하는 데 더 적합하다는 것에 동의합니다.따라서 스택의 Servlet 컨테이너 부분을 활용하지 않고 사용자 지정 컨트롤러 코드(URL에 매핑된 컨트롤러의 정확성, 입력 및 출력 개체의 매핑 및 검증, 표준 컨트롤러, 사용자 컨트롤러)를 사용하여 스프링 MVC 인프라를 동시에 테스트하려는 경우 MockMVC가 도움이 됩니다.

그러나 MockMVC에는 필터를 추가하는 방법도 있으므로 필터를 설명된 유형의 테스트에 참여시킬 수 있도록 설계되었습니다.때때로 필터는 컨트롤러 내부의 코드에 대해 기능적인 역할을 수행할 수 있으며 그렇지 않으면 MockMVC로 테스트할 수 없습니다.

이러한 모든 이론을 염두에 두고 저는 필터가 Spring Bootway로 설정되고 MockVMC와 함께 사용될 테스트에서 픽업되는 테스트를 위해 부팅 동작을 모방하려고 했습니다.여기 제가 사용하게 된 스니펫이 있습니다.부트 동작을 보다 정확하게 모방하고 일부 사용자 지정 MockMVC Builder로 추출하도록 확실히 향상될 수 있습니다.

@Autowired
private WebApplicationContext wac;

private MockMvc mockMvc;

@Before
public void setUp() {
    Collection<Filter> filterCollection = wac.getBeansOfType(Filter.class).values();
    Filter[] filters = filterCollection.toArray(new Filter[filterCollection.size()]);
    mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(filters).build();
}

이거 먹어봤어요?

import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;

...
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class AuthorizeTest {

    @Autowired
    private WebApplicationContext wac;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders
                .webAppContextSetup(wac)
                .apply(springSecurity())
                .build();
    }
    ...

}

저 같은 경우에는 401이 아니라 403입니다만, 이해하실 수 있습니다.

언급URL : https://stackoverflow.com/questions/26762209/integration-testing-spring-boot-with-mockmvc

반응형