Wednesday, July 18, 2012

Spring-test-mvc, @Configuration and 1 page test

I like how a very concise 1 page end to end controller test for a sample REST service is possible through a combination of @Configuration, Spring Testing Support and Spring-test-mvc.

Here is the test:

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package org.bk.webtest;
 
import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.server.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.server.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.server.setup.MockMvcBuilders.*;
 
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
 
import org.junit.Test;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.test.web.server.MockMvc;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
 
public class WebContextConfigurationTest {
 private final String createJson = "{\"id\":%d,\"first\":\"%s\",\"last\":\"%s\"}";
 private final String membersJson = "[{\"id\":1,\"first\":\"One\",\"last\":\"One\"},{\"id\":2,\"first\":\"Two\",\"last\":\"Two\"},{\"id\":3,\"first\":\"Three\",\"last\":\"Three\"}]";
 private final String updatedMembersJson = "[{\"id\":1,\"first\":\"One\",\"last\":\"OneUpdated\"},{\"id\":2,\"first\":\"Two\",\"last\":\"Two\"},{\"id\":3,\"first\":\"Three\",\"last\":\"Three\"}]";
  
 @Test
 public void testAWebFlow() throws Exception {
  MockMvc mockMvc = annotationConfigSetup(WebContextConfigurationTest.TestConfiguration.class)
   .build();
  mockMvc.perform(post("/members").contentType(MediaType.APPLICATION_JSON).body(String.format(createJson, 1,"One","One").getBytes()))
    .andExpect(status().isOk());
  mockMvc.perform(post("/members").contentType(MediaType.APPLICATION_JSON).body(String.format(createJson, 2,"Two","Two").getBytes()))
   .andExpect(status().isOk());
  mockMvc.perform(post("/members").contentType(MediaType.APPLICATION_JSON).body(String.format(createJson, 3,"Three","Three").getBytes()))
   .andExpect(status().isOk());
   
   
  mockMvc.perform(get("/members").contentType(MediaType.APPLICATION_JSON))
    .andExpect(status().isOk())
    .andExpect(content().string(containsString(membersJson)));
   
  mockMvc.perform(put("/members").contentType(MediaType.APPLICATION_JSON).body(String.format(createJson, 1,"One","OneUpdated").getBytes()))
   .andExpect(status().isOk());
   
  mockMvc.perform(get("/members").contentType(MediaType.APPLICATION_JSON))
   .andExpect(status().isOk())
   .andExpect(content().string(containsString(updatedMembersJson)));
   
  mockMvc.perform(get("/members/1").contentType(MediaType.APPLICATION_JSON))
   .andExpect(status().isOk())
   .andExpect(content().string(String.format(createJson, 1,"One","OneUpdated")));
   
  mockMvc.perform(delete("/members/1").contentType(MediaType.APPLICATION_JSON))
   .andExpect(status().isOk());
   
   
 }
 
 @Configuration
 @EnableWebMvc
 @ComponentScan(basePackages="org.bk.webtest")
 public static class TestConfiguration{
   
 }
}
 
@Controller
class MembersController{
 private Map<Integer, Member> memberDB = new HashMap<>();
 @RequestMapping(value = "/members", method = RequestMethod.GET)
    @ResponseBody
    public Collection<Member> list() {
        return this.memberDB.values();
    }
  
 @RequestMapping(value="/members", method=RequestMethod.POST)
 public @ResponseBody Member create(@RequestBody Member member){
  this.memberDB.put(member.getId(), member);
  return member;
 }
  
 @RequestMapping(value="/members", method=RequestMethod.PUT)
 public @ResponseBody Member update(@RequestBody Member member){
  this.memberDB.put(member.getId(), member);
  return member;
 }
  
 @RequestMapping(value="/members/{id}", method=RequestMethod.GET)
 public @ResponseBody Member get(@PathVariable("id") Integer id){
  return this.memberDB.get(id);
 }
  
 @RequestMapping(value="/members/{id}", method=RequestMethod.DELETE)
 public void delete(@PathVariable("id") Integer id){
  this.memberDB.remove(id);
 }
}
 
class Member{
 private Integer id;
 private String first;
 private String last;
  
 public Integer getId() {
  return id;
 }
 public void setId(Integer id) {
  this.id = id;
 }
 
 public String getFirst() {
  return first;
 }
  
 public void setFirst(String first) {
  this.first = first;
 }
 public String getLast() {
  return last;
 }
 public void setLast(String last) {
  this.last = last;
 }
}


This is a complete test which performs a test for a REST based controller supporting creating a new entity through Http POST, Updating it through a Http PUT, getting a list or an entity through Http GET, and deleting it through DELETE.

Just the following configures the complete Spring MVC!
1
2
3
4
5
6
@Configuration
 @EnableWebMvc
 @ComponentScan(basePackages="org.bk.webtest")
 public static class TestConfiguration{
   
 }

No comments:

Post a Comment