如何使用@PathVariable对Spring MVC控制器进行单元测试?

mar*_*ner 52 java spring unit-testing spring-mvc spring-test

我有一个类似于这个的简单注释控制器:

@Controller
public class MyController {
  @RequestMapping("/{id}.html")
  public String doSomething(@PathVariable String id, Model model) {
    // do something
    return "view";
  }
}
Run Code Online (Sandbox Code Playgroud)

我想用这样的单元测试来测试它:

public class MyControllerTest {
  @Test
  public void test() {
    MockHttpServletRequest request = new MockHttpServletRequest();
    request.setRequestURI("/test.html");
    new AnnotationMethodHandlerAdapter()
      .handle(request, new MockHttpServletResponse(), new MyController());
    // assert something
  }
}
Run Code Online (Sandbox Code Playgroud)

问题是AnnotationMethodHandlerAdapter.handler()方法抛出异常:

java.lang.IllegalStateException: Could not find @PathVariable [id] in @RequestMapping
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.resolvePathVariable(AnnotationMethodHandlerAdapter.java:642)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolvePathVariable(HandlerMethodInvoker.java:514)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:262)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:146)
Run Code Online (Sandbox Code Playgroud)

sca*_*a05 46

在基于Spring参考手册中的术语进行集成测试之后,我会打电话给你.做一些像这样的事情:

import static org.springframework.test.web.ModelAndViewAssert.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({/* include live config here
    e.g. "file:web/WEB-INF/application-context.xml",
    "file:web/WEB-INF/dispatcher-servlet.xml" */})
public class MyControllerIntegrationTest {

    @Inject
    private ApplicationContext applicationContext;

    private MockHttpServletRequest request;
    private MockHttpServletResponse response;
    private HandlerAdapter handlerAdapter;
    private MyController controller;

    @Before
    public void setUp() {
       request = new MockHttpServletRequest();
       response = new MockHttpServletResponse();
       handlerAdapter = applicationContext.getBean(HandlerAdapter.class);
       // I could get the controller from the context here
       controller = new MyController();
    }

    @Test
    public void testDoSomething() throws Exception {
       request.setRequestURI("/test.html");
       final ModelAndView mav = handlerAdapter.handle(request, response, 
           controller);
       assertViewName(mav, "view");
       // assert something
    }
}
Run Code Online (Sandbox Code Playgroud)

有关更多信息,我写了一篇关于集成测试Spring MVC注释博客文章.

  • 如果我的配置是在Java类而不是在xml文件中怎么办? (2认同)

Cli*_*ood 37

从Spring 3.2开始,有一种正确的方法可以以优雅和简单的方式对其进行测试.你将能够做到这样的事情:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("servlet-context.xml")
public class SampleTests {

  @Autowired
  private WebApplicationContext wac;

  private MockMvc mockMvc;

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

  @Test
  public void getFoo() throws Exception {
    this.mockMvc.perform(get("/foo").accept("application/json"))
        .andExpect(status().isOk())
        .andExpect(content().mimeType("application/json"))
        .andExpect(jsonPath("$.name").value("Lee"));
  }
}
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请查看http://blog.springsource.org/2012/11/12/spring-framework-3-2-rc1-spring-mvc-test-framework/

  • 好吧,在这里添加它们所以没有其他人必须做同样的挖掘.`import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;``import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;``import static org.springframework.test.web .servlet.result.MockMvcResultMatchers.jsonPath;``import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;``import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;` (9认同)
  • 在@Before this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); (4认同)
  • 而mimeType()实际上是contentType(),至少在我的版本中. (2认同)

tbr*_*lle 10

一个有前途的测试Spring MVC的框架 https://github.com/SpringSource/spring-test-mvc

  • 另请参阅:https://jira.springsource.org/browse/SPR-9211 - 如果感兴趣,请投票.:-) (2认同)