【问题标题】:How to test a Spring Boot handler Interceptor如何测试 Spring Boot 处理程序拦截器
【发布时间】:2017-10-02 18:09:08
【问题描述】:

我们正在尝试使用 Spring Boot 版本 1.4.0 在我们的 Spring Boot 应用程序中对我们的拦截器进行集成测试,但不确定如何;这是我们的应用程序设置

@Configuration
@EnableAutoConfiguration()
@ComponentScan
public class Application extends SpringBootServletInitializer {
  @Override
  protected SpringApplicationBuilderconfigure(SpringApplicationBuilder application) {
  return application.sources(Application.class);
}

然后我们通过扩展 WebMvcConfigurerAdapter 自定义了 webmvc

@Configuration
public class CustomServletContext extends WebMvcConfigurerAdapter{
  @Override
  public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(testInterceptor).addPathPatterns("/testapi/**");
  }
}

所以我们想测试拦截器,但我们不想真正启动应用程序,因为有很多依赖bean需要读取外部定义的属性文件来构造

我们尝试了以下方法

@SpringBootTest(classes = CustomServletContext.class)
@RunWith(SpringRunner.class)
public class CustomServletContextTest {

  @Autowired
  private ApplicationContext applicationContext;

  @Test
  public void interceptor_request_all() throws Exception {
    RequestMappingHandlerMapping mapping = (RequestMappingHandlerMapping) applicationContext
        .getBean("requestMappingHandlerMapping");
    assertNotNull(mapping);

    MockHttpServletRequest request = new MockHttpServletRequest("GET",
        "/test");

    HandlerExecutionChain chain = mapping.getHandler(request);

    Optional<TestInterceptor> containsHandler = FluentIterable
        .from(Arrays.asList(chain.getInterceptors()))
        .filter(TestInterceptor.class).first();

    assertTrue(containsHandler.isPresent());
  }
}

但它会改变 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有定义名为“requestMappingHandlerMapping”的 bean

我们是否需要创建一个 requestMappingHandlerMapping 的 bean 来测试拦截器?有什么神奇的方法可以在 spring boot 中做到这一点?

【问题讨论】:

  • 你想测试什么?春天?为什么要这么做?你的TestInterceptor?如果是这样,创建它的一个实例并调用HandlerInterceptor 方法并验证结果。这就是所谓的单元测试,即测试单元,也就是TestInterceptor
  • 我们要测试的是我们的拦截器实际上只是拦截配置的url,比如leveluplunch.com/blog/2014/07/09/…,但是我们不能像例子中那样使用“@SpringApplicationConfiguration(classes=Application.class)”
  • 所以您想测试 Spring 是否正确应用了 "/testapi/**" 模式,即您想测试 Spring?再说一遍,为什么?
  • 你是对的,因为我们不确定使用 /testapi/* 或 testapi/**
  • 嗯,它应该匹配/testapi/foo/bar吗?如果不是,请使用/testapi/*。如果是,请使用/testapi/**

标签: java spring spring-mvc spring-boot spring-boot-test


【解决方案1】:

你可以像这样创建一个测试:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = { MyIncludedConfig.class })
@ActiveProfiles("my_enabled_profile")
public class BfmSecurityInterceptorTest2 {

    public static final String TEST_URI = "/test";
    public static final String RESPONSE = "test";

    // this way you can provide any beans missing due to limiting the application configuration scope
    @MockBean
    private DataSource dataSource;

    @Autowired
    private TestRestTemplate testRestTemplate;

    @Test
    public void testInterceptor_Session_cookie_present_Authorized() throws Exception {

        ResponseEntity<String> responseEntity = testRestTemplate.getForEntity(TEST_URI, String.class);

        assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(responseEntity.getBody()).isEqualTo(RESPONSE);

    }

    @SpringBootApplication
    @RestController
    public static class TestApplication {

        @GetMapping(TEST_URI)
        public String test() {
            return RESPONSE;
        }

    }

}

备注

  • 拦截器只有在设置 SpringBootTest.WebEnvironment.RANDOM_PORT 时才起作用
  • 您必须提供足够的配置才能执行您的拦截器
  • 为了加快测试速度,您可以排除不需要的 bean 和配置,请参阅示例

【讨论】:

    猜你喜欢
    • 2018-07-24
    • 1970-01-01
    • 2018-08-09
    • 2014-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多