4

使用 MockMvc 创建单元测试我遇到了:

HttpRequestMethodNotSupportedException:不支持请求方法“POST”

这导致测试用例失败,预期为“200”但得到“405”。您可能在 Junit 中看到的一些附加内容是针对 Spring Rest Docs 的,可以忽略。例如 mockMvc 调用上的 @Rule 或 .andDo()。我已遵循以下文档Spring Rest Docs - Path Parameter并且似乎无法使其正常工作。

这是控制器:

@RestController("/transferObjects")
public class TransferObjectController {

    @RequestMapping(method=RequestMethod.GET, produces="application/json")
    public List<TransferObject> getTransferObjects(){
        // do some magic
        return null;
    }

    @RequestMapping(value = "/{name}", method=RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    public void addTransferObject(@PathVariable("name")String name){
        // do magic
    }

    @RequestMapping(value = "/{name}", method=RequestMethod.DELETE)
    @ResponseStatus(HttpStatus.OK)
    public void deleteTransferObject(@PathVariable("name")String name){
        // do magic
    }

这是Junit类:

public class TransferObjectControllerTest {

@Rule
public RestDocumentation restDocumentation = new RestDocumentation("target/generated-snippets");

private MockMvc mockMvc;

@Before
public void setUp() throws Exception {      
    this.mockMvc = MockMvcBuilders.standaloneSetup(new TransferObjectController())
            .apply(documentationConfiguration(this.restDocumentation))
            .build();
}

@Test
public void testAddTransferObject() throws Exception {
    this.mockMvc.perform(post("/transferObjects/{name}", "hi"))
        .andExpect(status().isOk()).andDo(document("transferObject",
                pathParameters(
                    parameterWithName("name").description("The name of the new Transfer Object to be created."))));
}

这是运行测试时的控制台:

11:20:48.148 [main] INFO  o.s.w.s.m.m.a.RequestMappingHandlerAdapter - Looking for @ControllerAdvice: org.springframework.test.web.servlet.setup.StubWebApplicationContext@5ab785fe
    11:20:48.205 [main] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Looking for exception mappings: org.springframework.test.web.servlet.setup.StubWebApplicationContext@5ab785fe
    11:20:48.283 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Initializing servlet ''
    11:20:48.307 [main] DEBUG o.s.w.c.s.StandardServletEnvironment - Adding [servletConfigInitParams] PropertySource with lowest search precedence
    11:20:48.307 [main] DEBUG o.s.w.c.s.StandardServletEnvironment - Adding [servletContextInitParams] PropertySource with lowest search precedence
    11:20:48.312 [main] DEBUG o.s.w.c.s.StandardServletEnvironment - Adding [systemProperties] PropertySource with lowest search precedence
    11:20:48.312 [main] DEBUG o.s.w.c.s.StandardServletEnvironment - Adding [systemEnvironment] PropertySource with lowest search precedence
    11:20:48.313 [main] DEBUG o.s.w.c.s.StandardServletEnvironment - Initialized StandardServletEnvironment with PropertySources [servletConfigInitParams,servletContextInitParams,systemProperties,systemEnvironment]
    11:20:48.313 [main] INFO  o.s.mock.web.MockServletContext - Initializing Spring FrameworkServlet ''
    11:20:48.313 [main] INFO  o.s.t.w.s.TestDispatcherServlet - FrameworkServlet '': initialization started
    11:20:48.318 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Unable to locate MultipartResolver with name 'multipartResolver': no multipart request handling provided
    11:20:48.318 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Using LocaleResolver [org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver@63238bf4]
    11:20:48.318 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Using ThemeResolver [org.springframework.web.servlet.theme.FixedThemeResolver@32b97305]
    11:20:48.319 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Using RequestToViewNameTranslator [org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator@2d2e6747]
    11:20:48.319 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Using FlashMapManager [org.springframework.web.servlet.support.SessionFlashMapManager@417e7d7d]
    11:20:48.319 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Published WebApplicationContext of servlet '' as ServletContext attribute with name [org.springframework.web.servlet.FrameworkServlet.CONTEXT.]
    11:20:48.319 [main] INFO  o.s.t.w.s.TestDispatcherServlet - FrameworkServlet '': initialization completed in 6 ms
    11:20:48.319 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Servlet '' configured successfully
    11:20:48.361 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - DispatcherServlet with name '' processing POST request for [/transferObjects/hi]
    11:20:48.364 [main] DEBUG o.s.t.w.s.s.StandaloneMockMvcBuilder$StaticRequestMappingHandlerMapping - Looking up handler method for path /transferObjects/hi
    11:20:48.368 [main] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
    11:20:48.369 [main] DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver - Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
    11:20:48.369 [main] DEBUG o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
    11:20:48.369 [main] WARN  o.s.web.servlet.PageNotFound - Request method 'POST' not supported
    11:20:48.370 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Null ModelAndView returned to DispatcherServlet with name '': assuming HandlerAdapter completed request handling
    11:20:48.370 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Successfully completed request
4

1 回答 1

2

看来我能够解决这个问题。

在运行测试时仔细查看控制台,我注意到:

Mapped "{[],methods=[GET],produces=[application/json]}" onto public java.util.List<common.to.TransferObject> sf.common.controller.TransferObjectController.getTransferObjects()
Mapped "{[/{name}],methods=[POST]}" onto public void sf.common.controller.TransferObjectController.addTransferObject(java.lang.String)
Mapped "{[/{name}],methods=[DELETE]}" onto public void sf.common.controller.TransferObjectController.deleteTransferObject(java.lang.String)

这表明它正在将控制器请求映射映射到该方法持有的特定 RequestMapping。@RestController("/transferObjects")实际上并没有将映射定义为父级。为此,我必须@RequestMapping("/transferObjects")@RestController.

因此,通过更改父映射,我现在可以使用以下测试用例:

@Test
public void testAddTransferObject() throws Exception {
    this.mockMvc.perform(post("/transferObjects/{name}", "hi"))
        .andExpect(status().isOk()).andDo(document("transferObject",
                pathParameters(
                    parameterWithName("name").description("The name of the new Transfer Object to be created."))));
}
于 2016-01-25T19:13:45.317 回答