Chapter 5: 测试Spring MVC

Spring Testing Framework提供了Spring MVC Test Framework,能够很方便的来测试Controller。同时Spring Boot也提供了Auto-configured Spring MVC tests更进一步简化了测试需要的配置工作。

本章节将分别举例说明在不使用Spring Boot和使用Spring Boot下如何对Spring MVC进行测试。

例子1:Spring

测试Spring MVC的关键是使用MockMvc对象,利用它我们能够在不需启动Servlet容器的情况下测试Controller的行为。

源代码SpringMvc_1_Test.java

  1. @EnableWebMvc
  2. @WebAppConfiguration
  3. @ContextConfiguration(classes = { FooController.class, FooImpl.class })
  4. public class SpringMvc_1_Test extends AbstractTestNGSpringContextTests {
  5. @Autowired
  6. private WebApplicationContext wac;
  7. private MockMvc mvc;
  8. @BeforeMethod
  9. public void prepareMockMvc() {
  10. this.mvc = webAppContextSetup(wac).build();
  11. }
  12. @Test
  13. public void testController() throws Exception {
  14. this.mvc.perform(get("/foo/check-code-dup").param("code", "123"))
  15. .andDo(print())
  16. .andExpect(status().isOk())
  17. .andExpect(content().string("true"));
  18. }
  19. }

在这段代码里,主要有三个步骤:

  1. 将测试类标记为@WebAppConfiguration
  2. 通过webAppContextSetup(wac).build()构建MockMvc
  3. 利用MockMvc对结果进行判断

例子2:Spring + Mock

在例子1里,FooController使用了一个实体FooImpl的Bean,实际上我们也可以提供一个Foo的mock bean来做测试,这样就能够更多的控制测试过程。如果你还不知道Mock那么请看Chapter 3: 使用Mockito

源代码SpringMvc_2_Test.java

  1. @EnableWebMvc
  2. @WebAppConfiguration
  3. @ContextConfiguration(classes = { FooController.class })
  4. @TestExecutionListeners(listeners = MockitoTestExecutionListener.class)
  5. public class SpringMvc_2_Test extends AbstractTestNGSpringContextTests {
  6. @Autowired
  7. private WebApplicationContext wac;
  8. @MockBean
  9. private Foo foo;
  10. private MockMvc mvc;
  11. @BeforeMethod
  12. public void prepareMockMvc() {
  13. this.mvc = webAppContextSetup(wac).build();
  14. }
  15. @Test
  16. public void testController() throws Exception {
  17. when(foo.checkCodeDuplicate(anyString())).thenReturn(true);
  18. this.mvc.perform(get("/foo/check-code-dup").param("code", "123"))
  19. .andDo(print())
  20. .andExpect(status().isOk())
  21. .andExpect(content().string("true"));
  22. }
  23. }

例子3:Spring Boot

Spring Boot提供了@WebMvcTest更进一步简化了对于Spring MVC的测试,我们提供了对应例子1的Spring Boot版本。

源代码BootMvc_1_Test.java

  1. @WebMvcTest
  2. @ContextConfiguration(classes = { FooController.class, FooImpl.class })
  3. public class BootMvc_1_Test extends AbstractTestNGSpringContextTests {
  4. @Autowired
  5. private MockMvc mvc;
  6. @Test
  7. public void testController() throws Exception {
  8. this.mvc.perform(get("/foo/check-code-dup").param("code", "123"))
  9. .andDo(print())
  10. .andExpect(status().isOk())
  11. .andExpect(content().string("true"));
  12. }
  13. }

在这里,我们不需要自己构建MockMvc,直接使用@Autowired注入就行了,是不是很方便?

例子4:Spring Boot + Mock

这个是对应例子2的Spring Boot版本,源代码BootMvc_2_Test.java

  1. @WebMvcTest
  2. @ContextConfiguration(classes = { FooController.class })
  3. @TestExecutionListeners(listeners = MockitoTestExecutionListener.class)
  4. public class BootMvc_2_Test extends AbstractTestNGSpringContextTests {
  5. @Autowired
  6. private MockMvc mvc;
  7. @MockBean
  8. private Foo foo;
  9. @Test
  10. public void testController() throws Exception {
  11. when(foo.checkCodeDuplicate(anyString())).thenReturn(true);
  12. this.mvc.perform(get("/foo/check-code-dup").param("code", "123"))
  13. .andDo(print())
  14. .andExpect(status().isOk())
  15. .andExpect(content().string("true"));
  16. }
  17. }

参考文档