1、单元测试的目的前端
简单来讲就是在咱们增长或者改动一些代码之后对全部逻辑的一个检测,尤为是在咱们后期修改后(不管是增长新功能,修改bug),均可以作到从新测试的工做。以减小咱们在发布的时候出现更过甚至是出现以前解决了的问题再次重现。java
这里主要是使用MockMvc对咱们的系统的Controller进行单元测试。web
对数据库的操做使用事务实现回滚,及对数据库的增删改方法结束后将会还远数据库。spring
2、MockMvc的使用数据库
一、首先咱们上一个例子,apache
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.Before; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.RequestBuilder; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.context.WebApplicationContext; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** * Created by zhengcanrui on 16/8/11. */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"classpath:spring/applicationContext-*xml"}) //配置事务的回滚,对数据库的增删改都会回滚,便于测试用例的循环利用 @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) @Transactional @WebAppConfiguration public class Test { //记得配置log4j.properties ,的命令行输出水平是debug protected Log logger= LogFactory.getLog(TestBase.class); protected MockMvc mockMvc; @Autowired protected WebApplicationContext wac; @Before() //这个方法在每一个方法执行以前都会执行一遍 public void setup() { mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); //初始化MockMvc对象 } @org.junit.Test public void getAllCategoryTest() throws Exception { String responseString = mockMvc.perform( get("/categories/getAllCategory") //请求的url,请求的方法是get .contentType(MediaType.APPLICATION_FORM_URLENCODED) //数据的格式 .param("pcode","root") //添加参数 ).andExpect(status().isOk()) //返回的状态是200 .andDo(print()) //打印出请求和相应的内容 .andReturn().getResponse().getContentAsString(); //将相应的数据转换为字符串 System.out.println("--------返回的json = " + responseString); } }
Spring MVC的测试每每看似比较复杂。其实他的不一样在于,他须要一个ServletContext来模拟咱们的请求和响应。可是Spring也针对Spring MVC 提供了请求和响应的模拟测试接口,以方便咱们的单元测试覆盖面不仅是service,dao层。json
二、代码解释:spring-mvc
@webappconfiguration是一级注释,用于声明一个ApplicationContext集成测试加载WebApplicationContext。做用是模拟ServletContexttomcat
@ContextConfiguration:由于controller,component等都是使用注解,须要注解指定spring的配置文件,扫描相应的配置,将类初始化等。mvc
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) @Transactional
上面两句的做用是,让咱们对数据库的操做会事务回滚,如对数据库的添加操做,在方法结束以后,会撤销咱们对数据库的操做。
为何要事务回滚?
方法解析:
注意事项:
三、后台的返回数据中,最好带上咱们对数据库的修改的结果返回的前端。
为何要在data中返回一个修改或者添加的对象
咱们发送一个添加操做,添加一个SoftInfo对象,SoftInfo类定义以下:
public class SoftInfo { private String id; private String name; }
添加完以后,因为咱们进行了单元测试的事务回滚,咱们将不能再数据库中看咱们咱们的的添加操做,没法判断操做是否成功。
为了解决上面的问题,咱们能够在返回的json的数据中添加一个“data”字段,解析该json中的data字段数据,判断咱们的添加操做是否成功的。json格式以下:
{ "status":200, "data":{"id":"2","name":"测试"} }
咱们可使用andExpect方法对返回的数据进行判断,用“$.属性”获取里面的数据,如我要获取返回数据中的"data.name",能够写成"$.data.name"。下面的例子是判断返回的data.name=“测试”。
@Test public void testCreateSeewoAccountUser() throws Exception { mockMvc.perform(post("/users") .contentType(MediaType.APPLICATION_FORM_URLENCODED) ).andExpect(status().isOk()) .andExpect(jsonPath("$.data.name", is("测试")))) .andExpect(jsonPath("$.data.createTime", notNullValue())) ; }
3、遇到的问题
一、发送一个被@ResponseBody标识的参数,一直到400错误。 即没法发送一个json格式的数据到Controller层。
解决方法1:
SoftInfo softInfo = new SoftInfo();
//设置值
ObjectMapper mapper = new ObjectMapper(); ObjectWriter ow = mapper.writer().withDefaultPrettyPrinter(); java.lang.String requestJson = ow.writeValueAsString(softInfo); String responseString = mockMvc.perform( post("/softs").contentType(MediaType.APPLICATION_JSON).content(requestJson)).andDo(print()) .andExpect(status().isOk()).andReturn().getResponse().getContentAsString();
解决方法2:使用com.alibaba.fastjson.JSONObject将对象转换为Json数据
SoftInfo softInfo = new SoftInfo(); //。。。设置值 String requestJson = JSONObject.toJSONString(folderInfo); String responseString = mockMvc.perform( post("/softs").contentType(MediaType.APPLICATION_JSON).content(requestJson)).andDo(print()) .andExpect(status().isOk()).andReturn().getResponse().getContentAsString();
注意上面contentType须要设置成MediaType.APPLICATION_JSON,即声明是发送“application/json”格式的数据。使用content方法,将转换的json数据放到request的body中。
二、java.lang.NoClassDefFoundError: com/jayway/jsonpath/InvalidPathException
缺乏了jar包:
能够添加一下的maven依赖
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>0.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path-assert</artifactId>
<version>0.8.1</version>
<scope>test</scope>
</dependency>
学习连接:https://www.petrikainulainen.net/spring-mvc-test-tutorial/
致谢:感谢您的阅读!