代码之家  ›  专栏  ›  技术社区  ›  user2813807

带二进制响应的弹簧引导2测试

  •  2
  • user2813807  · 技术社区  · 6 年前

    我有一个返回zip文件的服务。它在dev/prod中运行良好,一个简单的get/content/id/zip将在我的浏览器中下载该文件。

    @GetMapping(value = "/content/{id}/zip")
    public ResponseEntity<byte[]> getContentZip(@PathVariable String id) {
            byte[] zip = ...
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType("application/zip"));
            ResponseEntity<byte[]> response = new ResponseEntity<>(zip, headers, HttpStatus.OK);
            return response;
    }
    

    测试有问题:

    ...
    MvcResult result = restStudyMockMvc.perform(get("/content/{id}/zip", content.getId()))
                    .andExpect(status().isOk())
                    .andExpect(content().contentType("application/zip")).andReturn();
    
    byte[] bytes = result.getResponse().getContentAsByteArray();
    assertThat(bytes).isNotEmpty();
    ...
    

    它与弹簧套1.5配合使用。 因为我升级到了SpringBoot2。它给了我一个“找不到可接受的表示”例外:

    11:04:21.244 [main] DEBUG i.o.v.web.ExceptionControllerAdvice - org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
    org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
        at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:287)
        at org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(HttpEntityMethodProcessor.java:218)
        at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:82)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:119)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:870)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:776)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:870)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855)
        at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:66)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
        at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:166)
        at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
        at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:166)
        at io.osimis.vsol.web.StudyTest.getStudyZip(StudyTest.java:376)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
        at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
        at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
        at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
        at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
        at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
        at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
        at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
        at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
        at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
        at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
        at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    

    感谢您的帮助:)

    1 回复  |  直到 6 年前
        1
  •  2
  •   Lars K.    5 年前

    也许有点晚了,但我还是犯了同样的错误,在寻找解决方案时发现了这个问题。

    在我的案例中,错误是我手动注册了 HttpMessageConverter 在我的测试中。

    this.mockMvc = MockMvcBuilders
                    ...
                    .setMessageConverters(myJsonHttpMessageConverter)
                    .build();
    

    通过调试,我发现SpringMVC的内部逻辑是:

    • 如果配置了转换器,请仅使用此转换器。
    • 如果没有配置,请添加所有默认转换器。

    这是相关的代码 org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport :

    protected final List<HttpMessageConverter<?>> getMessageConverters() {
        if (this.messageConverters == null) {
            this.messageConverters = new ArrayList<>();
            configureMessageConverters(this.messageConverters);
            if (this.messageConverters.isEmpty()) {
                addDefaultHttpMessageConverters(this.messageConverters);
            }
            extendMessageConverters(this.messageConverters);
        }
        return this.messageConverters;
    }
    

    为了解决这个问题,你可以 删除自定义转换器 所以所有的默认转换器都被使用,或者-如果你像我一样需要它的话- 添加 ByteArrayHttpMessageConverter 在测试设置中。

    this.mockMvc = MockMvcBuilders
                    ...
                    .setMessageConverters(myJsonHttpMessageConverter, new ByteArrayHttpMessageConverter())
                    .build();