【问题标题】:Spring boot test not recognizing servletSpring Boot 测试无法识别 servlet
【发布时间】:2017-09-06 11:33:43
【问题描述】:

我有 Spring Boot 应用程序,我想测试它。我不使用 Spring 控制器,但我使用带有服务方法的 Servlet。我也有提供 ServletRegistrationBean 的配置类。 但是每次当我尝试执行模拟请求时,我都会收到 404 错误。根本没有调用 servlet。我认为 Spring 没有找到这个 servlet。我该如何解决?当我在 localhost 启动应用程序时,一切正常。

测试:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class SpringDataProcessorTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void retrieveByRequest() throws Exception{
        mockMvc.perform(buildRetrieveCustomerByIdRequest("1")).andExpect(status().isOk());

    }

    private MockHttpServletRequestBuilder buildRetrieveCustomerByIdRequest(String id) throws Exception {
        return get(String.format("/path/get('%s')", id)).contentType(APPLICATION_JSON_UTF8);
    }
}

配置:

@Configuration
public class ODataConfiguration extends WebMvcConfigurerAdapter {
    public String urlPath = "/path/*";


    @Bean
    public ServletRegistrationBean odataServlet(MyServlet servlet) {
        return new ServletRegistrationBean(servlet, new String[] {odataUrlPath});
    }
}

MyServlet:

@Component
public class MyServlet extends HttpServlet {

    @Autowired
    private ODataHttpHandler handler;


    @Override
    @Transactional
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            handler.process(req, resp);
        } catch (Exception e) {
            log.error("Server Error occurred", e);
            throw new ServletException(e);
        }
    }
}

【问题讨论】:

  • 您不能为此使用MockMvcMockMvc 在内部拥有一个特定的 DispatcherServlet,旨在用于 Spring MVC 测试(即存在于 DispatcherServlet 中的所有内容)。

标签: java spring servlets junit spring-boot-test


【解决方案1】:

如果您真的想使用 MockMvc 而不是 Servlet 来测试您的代码,请使用 HttpRequestHandler 并使用 SimpleUrlHandlerMapping 将其映射到 URL。

类似于以下内容。

@Bean
public HttpRequestHandler odataRequestHandler(ODataHttpHandler handler) {
    return new HttpRequestHandler() {
        public void handleRequest() {
            try {
                handler.process(req, resp);
            } catch (Exception e) {
                log.error("Server Error occurred", e);
                throw new ServletException(e);
            }
        }
    }
}

对于映射

@Bean
public SimpleUrlHandlerMapping simpleUrlHandlerMapping() {
    SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
    mapping.setUrlMap(Collections.singletonMap(odataUrlPath, "odataRequestHandler"); 
    return mapping;
}

另一种解决方案是将其包装在控制器而不是 servlet 中。

@Controller
public class ODataController {

    private final ODataHttpHandler handler;

    public ODataController(ODataHttpHandler handler) {
        this.handler=handler;
    }

    @RequestMapping("/path/*")
    public void process(HttpServletRequest request, HttpServletResponse response) throws ServletException {
        try {
            handler.process(req, resp);
        } catch (Exception e) {
            log.error("Server Error occurred", e);
            throw new ServletException(e);
        }
    }
}

无论哪种方式,您的处理程序都应该由DispatcherServlet 服务/处理,因此可以使用MockMvc 进行测试。

【讨论】:

  • SimpleUrlHandlerMapping 不起作用。但是如果在 HttpRequestHandler 上面指定 @Bean(name="/path/*) 一切正常。但是在这个请求中 servletPath 字段为空。如果我通过 MockHttpServletRequestBuilder 指定它,则不会再次处理请求。
  • 为什么需要servlet路径?
  • OData 处理器中需要 Servlet 路径。没有它,应用程序将失败。
  • 那么您需要在该路径上映射DispatcherServlet。但是不确定您是否想做所有这些只是为了完成这项工作。为什么不简单地使用MockHttpServletRequestMockHttpServletResponse 对其进行测试,然后从上下文中获取servlet 并调用所需的方法。
  • 你太棒了!我用这种方法做到了,但想知道这项工作是否可以通过 mockMvc 完成:)
猜你喜欢
  • 2021-09-07
  • 1970-01-01
  • 2021-12-08
  • 2015-09-25
  • 2019-02-26
  • 2017-10-04
  • 1970-01-01
  • 2022-12-19
相关资源
最近更新 更多