Spring MVC 单元测试

常规的方法则是启动WEB服务器 测试 出错 停掉WEB 改代码 重启WEB 测试 

大量的时间都浪费在WEB服务器的启动上

今天给大家介绍一种不用启动WEB 直接采用单元测试的方法来测试请求是否准确 

该方法基于SpringMVC 与 Spring Test 框架






[java]  view plain copy
  1. package com.spring;  
  2.   
  3. import java.io.FileNotFoundException;  
  4. import java.io.IOException;  
  5. import java.util.ArrayList;  
  6. import java.util.List;  
  7. import java.util.Map;  
  8. import javax.servlet.http.HttpServletRequest;  
  9. import javax.servlet.http.HttpServletResponse;  
  10.   
  11. import org.json.JSONObject;  
  12. import org.springframework.beans.factory.annotation.Autowired;  
  13. import org.springframework.http.MediaType;  
  14. import org.springframework.stereotype.Controller;  
  15. import org.springframework.ui.Model;  
  16. import org.springframework.web.bind.annotation.PathVariable;  
  17. import org.springframework.web.bind.annotation.RequestMapping;  
  18. import org.springframework.web.bind.annotation.RequestMethod;  
  19. import org.springframework.web.bind.annotation.ResponseBody;  
  20. import org.springframework.web.context.ContextLoader;  
  21. import org.springframework.web.context.WebApplicationContext;  
  22. import org.springframework.web.context.support.WebApplicationContextUtils;  
  23. import org.springframework.web.servlet.ModelAndView;  
  24.   
  25. @Controller  
  26. @RequestMapping(value = "/spring")  
  27. public class Action {  
  28.   
  29.     @Autowired  
  30.     Teacher teacher;  
  31.     // spring 支持restful的格式  
  32.       
  33.     @ResponseBody  
  34.     @RequestMapping(value = "/rest/{ownerId}.do", method = RequestMethod.GET)  
  35.     public String findOwner(@PathVariable String ownerId, Model model,  
  36.             HttpServletResponse rep) throws IOException {  
  37.         return ownerId;  
  38.     }  
  39.   
  40.     @RequestMapping(value = "/test.do", method = RequestMethod.GET)  
  41.     public String testa(Model model, HttpServletResponse rep)  
  42.             throws IOException {  
  43.         model.addAttribute("abc""efd");  
  44.         model.addAttribute(teacher);  
  45.         return "a";  
  46.     }  
  47.   
  48.     @ResponseBody  
  49.     // 理论上可以@ResponseBody 支持直接返回teacher对象 但是3.2里有问题 我们还是老实返回字符串吧  
  50.     @RequestMapping(value = "/testb.do", method = RequestMethod.GET)  
  51.     public String testb(Model model, HttpServletResponse rep,  
  52.             HttpServletRequest req, String ex) throws IOException {  
  53.         // WEB中获得SPRING容器  
  54.         WebApplicationContext wac = WebApplicationContextUtils  
  55.                 .getRequiredWebApplicationContext(req.getServletContext());  
  56.         return new JSONObject(wac.getBean(Teacher.class)).toString();  
  57.     }  
  58.   
  59.     @ResponseBody  
  60.     @RequestMapping(value = "/post.do", method = RequestMethod.POST)  
  61.     public String post(Model model, HttpServletResponse rep,  
  62.             HttpServletRequest req, String ex) throws IOException {  
  63.         return new JSONObject(req.getParameterMap()).toString();  
  64.     }  
  65.   
  66. }  

[java]  view plain copy
  1.   

再上单元测试代码

[java]  view plain copy
  1. import java.awt.print.Printable;  
  2. import java.io.IOException;  
  3.   
  4. import javax.servlet.http.HttpServletResponse;  
  5.   
  6. import org.junit.Before;  
  7. import org.junit.Test;  
  8. import org.junit.runner.RunWith;  
  9. import org.springframework.beans.factory.annotation.Autowired;  
  10. import org.springframework.http.MediaType;  
  11. import org.springframework.test.context.ContextConfiguration;  
  12. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
  13. import org.springframework.test.context.web.WebAppConfiguration;  
  14. import org.springframework.test.web.servlet.MockMvc;  
  15. import org.springframework.test.web.servlet.ResultHandler;  
  16. import org.springframework.test.web.servlet.ResultMatcher;  
  17. import org.springframework.ui.Model;  
  18. import org.springframework.test.context.transaction.TransactionConfiguration;  
  19. import org.springframework.transaction.annotation.Transactional;  
  20. import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;  
  21. import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;  
  22. import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;  
  23. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;  
  24. import org.springframework.web.bind.annotation.RequestMapping;  
  25. import org.springframework.web.bind.annotation.RequestMethod;  
  26. import org.springframework.web.context.WebApplicationContext;  
  27.   
  28. @RunWith(SpringJUnit4ClassRunner.class)  
  29. @WebAppConfiguration  
  30. @ContextConfiguration(locations = { "classpath:applicationContext.xml" })  
  31. //当然 你可以声明一个事务管理 每个单元测试都进行事务回滚 无论成功与否  
  32. @TransactionConfiguration(defaultRollback = true)  
  33. //记得要在XML文件中声明事务哦~~~我是采用注解的方式  
  34. @Transactional  
  35. public class ExampleTests {  
  36.   
  37.     @Autowired  
  38.     private WebApplicationContext wac;  
  39.   
  40.     private MockMvc mockMvc;  
  41.   
  42.     @Before  
  43.     public void setup() {  
  44.         // webAppContextSetup 注意上面的static import  
  45.         // webAppContextSetup 构造的WEB容器可以添加fileter 但是不能添加listenCLASS  
  46.         // WebApplicationContext context =  
  47.         // ContextLoader.getCurrentWebApplicationContext();  
  48.         // 如果控制器包含如上方法 则会报空指针  
  49.         this.mockMvc = webAppContextSetup(this.wac).build();  
  50.     }  
  51.   
  52.     @Test  
  53.         //有些单元测试你不希望回滚  
  54.         @Rollback(false)  
  55.     public void ownerId() throws Exception {  
  56.         mockMvc.perform((get("/spring/rest/4.do"))).andExpect(status().isOk())  
  57.                 .andDo(print());  
  58.     }  
  59.   
  60.     @Test  
  61.     public void test() throws Exception {  
  62.         mockMvc.perform((get("/spring/test.do"))).andExpect(status().isOk())  
  63.                 .andDo(print())  
  64.                 .andExpect(model().attributeHasNoErrors("teacher"));  
  65.     }  
  66.   
  67.     @Test  
  68.     public void testb() throws Exception {  
  69.         mockMvc.perform((get("/spring/testb.do"))).andExpect(status().isOk())  
  70.                 .andDo(print());  
  71.     }  
  72.   
  73.     @Test  
  74.     public void getAccount() throws Exception {  
  75.         mockMvc.perform((post("/spring/post.do").param("abc""def")))  
  76.                 .andExpect(status().isOk()).andDo(print());  
  77.     }  
  78.   
  79. }  




[java]  view plain copy
  1. package com.spring;  
  2.   
  3. import java.io.FileNotFoundException;  
  4. import java.io.IOException;  
  5. import java.util.ArrayList;  
  6. import java.util.List;  
  7. import java.util.Map;  
  8. import javax.servlet.http.HttpServletRequest;  
  9. import javax.servlet.http.HttpServletResponse;  
  10.   
  11. import org.json.JSONObject;  
  12. import org.springframework.beans.factory.annotation.Autowired;  
  13. import org.springframework.http.MediaType;  
  14. import org.springframework.stereotype.Controller;  
  15. import org.springframework.ui.Model;  
  16. import org.springframework.web.bind.annotation.PathVariable;  
  17. import org.springframework.web.bind.annotation.RequestMapping;  
  18. import org.springframework.web.bind.annotation.RequestMethod;  
  19. import org.springframework.web.bind.annotation.ResponseBody;  
  20. import org.springframework.web.context.ContextLoader;  
  21. import org.springframework.web.context.WebApplicationContext;  
  22. import org.springframework.web.context.support.WebApplicationContextUtils;  
  23. import org.springframework.web.servlet.ModelAndView;  
  24.   
  25. @Controller  
  26. @RequestMapping(value = "/spring")  
  27. public class Action {  
  28.   
  29.     @Autowired  
  30.     Teacher teacher;  
  31.     // spring 支持restful的格式  
  32.       
  33.     @ResponseBody  
  34.     @RequestMapping(value = "/rest/{ownerId}.do", method = RequestMethod.GET)  
  35.     public String findOwner(@PathVariable String ownerId, Model model,  
  36.             HttpServletResponse rep) throws IOException {  
  37.         return ownerId;  
  38.     }  
  39.   
  40.     @RequestMapping(value = "/test.do", method = RequestMethod.GET)  
  41.     public String testa(Model model, HttpServletResponse rep)  
  42.             throws IOException {  
  43.         model.addAttribute("abc""efd");  
  44.         model.addAttribute(teacher);  
  45.         return "a";  
  46.     }  
  47.   
  48.     @ResponseBody  
  49.     // 理论上可以@ResponseBody 支持直接返回teacher对象 但是3.2里有问题 我们还是老实返回字符串吧  
  50.     @RequestMapping(value = "/testb.do", method = RequestMethod.GET)  
  51.     public String testb(Model model, HttpServletResponse rep,  
  52.             HttpServletRequest req, String ex) throws IOException {  
  53.         // WEB中获得SPRING容器  
  54.         WebApplicationContext wac = WebApplicationContextUtils  
  55.                 .getRequiredWebApplicationContext(req.getServletContext());  
  56.         return new JSONObject(wac.getBean(Teacher.class)).toString();  
  57.     }  
  58.   
  59.     @ResponseBody  
  60.     @RequestMapping(value = "/post.do", method = RequestMethod.POST)  
  61.     public String post(Model model, HttpServletResponse rep,  
  62.             HttpServletRequest req, String ex) throws IOException {  
  63.         return new JSONObject(req.getParameterMap()).toString();  
  64.     }  
  65.   
  66. }  

[java]  view plain copy
  1.   

再上单元测试代码

[java]  view plain copy
  1. import java.awt.print.Printable;  
  2. import java.io.IOException;  
  3.   
  4. import javax.servlet.http.HttpServletResponse;  
  5.   
  6. import org.junit.Before;  
  7. import org.junit.Test;  
  8. import org.junit.runner.RunWith;  
  9. import org.springframework.beans.factory.annotation.Autowired;  
  10. import org.springframework.http.MediaType;  
  11. import org.springframework.test.context.ContextConfiguration;  
  12. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
  13. import org.springframework.test.context.web.WebAppConfiguration;  
  14. import org.springframework.test.web.servlet.MockMvc;  
  15. import org.springframework.test.web.servlet.ResultHandler;  
  16. import org.springframework.test.web.servlet.ResultMatcher;  
  17. import org.springframework.ui.Model;  
  18. import org.springframework.test.context.transaction.TransactionConfiguration;  
  19. import org.springframework.transaction.annotation.Transactional;  
  20. import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;  
  21. import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;  
  22. import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;  
  23. import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;  
  24. import org.springframework.web.bind.annotation.RequestMapping;  
  25. import org.springframework.web.bind.annotation.RequestMethod;  
  26. import org.springframework.web.context.WebApplicationContext;  
  27.   
  28. @RunWith(SpringJUnit4ClassRunner.class)  
  29. @WebAppConfiguration  
  30. @ContextConfiguration(locations = { "classpath:applicationContext.xml" })  
  31. //当然 你可以声明一个事务管理 每个单元测试都进行事务回滚 无论成功与否  
  32. @TransactionConfiguration(defaultRollback = true)  
  33. //记得要在XML文件中声明事务哦~~~我是采用注解的方式  
  34. @Transactional  
  35. public class ExampleTests {  
  36.   
  37.     @Autowired  
  38.     private WebApplicationContext wac;  
  39.   
  40.     private MockMvc mockMvc;  
  41.   
  42.     @Before  
  43.     public void setup() {  
  44.         // webAppContextSetup 注意上面的static import  
  45.         // webAppContextSetup 构造的WEB容器可以添加fileter 但是不能添加listenCLASS  
  46.         // WebApplicationContext context =  
  47.         // ContextLoader.getCurrentWebApplicationContext();  
  48.         // 如果控制器包含如上方法 则会报空指针  
  49.         this.mockMvc = webAppContextSetup(this.wac).build();  
  50.     }  
  51.   
  52.     @Test  
  53.         //有些单元测试你不希望回滚  
  54.         @Rollback(false)  
  55.     public void ownerId() throws Exception {  
  56.         mockMvc.perform((get("/spring/rest/4.do"))).andExpect(status().isOk())  
  57.                 .andDo(print());  
  58.     }  
  59.   
  60.     @Test  
  61.     public void test() throws Exception {  
  62.         mockMvc.perform((get("/spring/test.do"))).andExpect(status().isOk())  
  63.                 .andDo(print())  
  64.                 .andExpect(model().attributeHasNoErrors("teacher"));  
  65.     }  
  66.   
  67.     @Test  
  68.     public void testb() throws Exception {  
  69.         mockMvc.perform((get("/spring/testb.do"))).andExpect(status().isOk())  
  70.                 .andDo(print());  
  71.     }  
  72.   
  73.     @Test  
  74.     public void getAccount() throws Exception {  
  75.         mockMvc.perform((post("/spring/post.do").param("abc""def")))  
  76.                 .andExpect(status().isOk()).andDo(print());  
  77.     }  
  78.   
  79. }  


你可能感兴趣的:(Spring MVC 单元测试)