Sam's Notes | Sam Blog

梦想还是要有的,万一实现了呢

0%

SpringTesting (三) Spring MVC Test Framework

Spring MVC Test Framework建立在Servlet API mock objects基础上,他不需要一个运行的Servlet容器,
不需要,不需要,不需要!
他使用DispatcherServlet来提供完整Spring MVC的支持,使用TestContext framework来加载实际的Spring各个配置。

Server-Side Tests

Spring MVC Test的目的:提供一种有效的利用DispatcherServlet所伴生的requests和responses来测试controller的方式。
例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

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

@Autowired
private WebApplicationContext wac;

private MockMvc mockMvc;

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

@Test
public void getAccount() throws Exception {
this.mockMvc.perform(get("/accounts/1").accept(MediaType.parseMediaType("application/json;charset=UTF-8")))
.andExpect(status().isOk())
.andExpect(content().contentType("application/json"))
.andExpect(jsonPath("$.name").value("Lee"));
}

}

Setup Options

  • webAppContextSetup

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    @ContextConfiguration("my-servlet-context.xml")
    public class MyWebTests {

    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;

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

    // ...

    }
  • standaloneSetup(简单controller实例)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class MyWebTests {

    private MockMvc mockMvc;

    @Before
    public void setup() {
    this.mockMvc = MockMvcBuilders.standaloneSetup(new AccountController()).build();
    }

    // ...

    }

如何选择?
webAppContextSetup 方式:加载并缓存完整的Spring MVC配置,

standaloneSetup 方式:更像一个单元测试

他们就像集成测试Vs单元测试。

Performing Requests

1
2
3
4
5
6
7
8
9
mockMvc.perform(post("/hotels/{id}", 42).accept(MediaType.APPLICATION_JSON));

mockMvc.perform(fileUpload("/doc").file("a1", "ABC".getBytes("UTF-8")));

mockMvc.perform(get("/hotels?foo={foo}", "bar"));

mockMvc.perform(get("/hotels").param("foo", "bar"));

mockMvc.perform(get("/app/main/hotels/{id}").contextPath("/app").servletPath("/main"))

测试预期

测试预期结果可以在Requests后面加一个或多个 .andExpect(..)

1
2
3
4
mockMvc.perform(post("/persons"))
.andDo(print()) // static import from MockMvcResultHandlers, can print all the available result data
.andExpect(status().isOk())
.andExpect(model().attributeHasErrors("person"));

如果需要直接访问结果来验证一些其他数据,在测试预期最后加上 .andReturn()

1
MvcResult mvcResult = mockMvc.perform(post("/persons")).andExpect(status().isOk()).andReturn();

HtmlUnit Integration TODO

Client-Side REST Tests

使用RestTemplate进行客户端的REST测试。

1
2
3
4
5
6
7
8
RestTemplate restTemplate = new RestTemplate();

MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate);
mockServer.expect(requestTo("/greeting")).andRespond(withSuccess("Hello world", MediaType.TEXT_PLAIN));

// use RestTemplate ...

mockServer.verify();

PetClinic Example

Spring官方提供的完整案例Github