Junit测试Controller(MockMVC使用),以及JUnit Generator使用方法
一、单元测试的目的
简单来说就是在我们增加或者改动一些代码以后对所有逻辑的一个检测,尤其是在我们后期修改后(不论是增加新功能,修改bug),都可以做到重新测试的工作。以减少我们在发布的时候出现更过甚至是出现之前解决了的问题再次重现。
这里主要是使用MockMvc对我们的系统的Controller进行单元测试。
对数据库的操作使用事务实现回滚,及对数据库的增删改方法结束后将会还远数据库。
二、MockMvc的使用
1、首先我们上一个例子
package com.greenline.ai.platform.web.home.controller.face;
import com.alibaba.fastjson.JSON;
import com.greenline.ai.platform.common.statics.Constant;
import com.greenline.ai.platform.model.bo.org.OrganizeOpenConfigBo;
import com.greenline.ai.platform.web.home.Application;
import org.junit.Assert;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import java.util.Date;
import static com.sun.org.apache.xerces.internal.util.PropertyState.is;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* VeriFaceController Tester.
*
* @author <Authors name>
* @since <pre>三月 8, 2019</pre>
* @version 1.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class VeriFaceControllerTest {
@Autowired
private WebApplicationContext context;
private MockMvc mvc;
@Before
public void setUp() throws Exception {
mvc = MockMvcBuilders.webAppContextSetup(context).build();//建议使ç¨è¿ç§
}
/**
*
* Method: getOrgOpenConfig(@RequestBody @ApiParam(name = "organizeCode",value = "组织机构编码") OrganizeOpenConfig organizeOpenConfig)
*
*/
@Test
public void testGetOrgOpenConfig() throws Exception {
OrganizeOpenConfigBo organizeOpenConfig=new OrganizeOpenConfigBo();
organizeOpenConfig.setConfigKey(Constant.DEFAULT_RETURN_NUM_KEY);
organizeOpenConfig.setOrganizeCode("c9ace68e78c345489bcf3007f9c04f6a");
MockHttpServletResponse response=mvc.perform(MockMvcRequestBuilders.post("/union/face/getOrgOpenConfig")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(JSON.toJSONString(organizeOpenConfig)))
.andExpect(status().isOk()) // 期待返回状态吗码200
.andExpect(jsonPath("$.configValue").value("53"))
.andDo(MockMvcResultHandlers.print())
.andReturn()
.getResponse();
String result=response.getContentAsString();
OrganizeOpenConfigBo organizeOpenConfigBo=JSON.toJavaObject(JSON.parseObject(result), OrganizeOpenConfigBo.class);
Assert.assertEquals("53",organizeOpenConfigBo.getConfigValue());
}
/**
*
* Method: orgOpenConfigEdit(@RequestBody @ApiParam(name = "organizeOpenConfigBo",value = "机构配置信息") OrganizeOpenConfigBo organizeOpenConfigBo)
*
*/
@Test
public void testOrgOpenConfigEdit() throws Exception {
OrganizeOpenConfigBo organizeOpenConfig=new OrganizeOpenConfigBo();
organizeOpenConfig.setId(50L);
organizeOpenConfig.setGmtCreated(new Date());
organizeOpenConfig.setGmtModified(new Date());
organizeOpenConfig.setIsDeleted(Constant.NOT_DELETED);
organizeOpenConfig.setConfigKey(Constant.DEFAULT_RETURN_NUM_KEY);
organizeOpenConfig.setConfigValue(Constant.DEFAULT_RETURN_NUM_VALUE);
organizeOpenConfig.setOrganizeCode("c9ace68e78c345489bcf3007f9c04f6a");
MockHttpServletResponse response=mvc.perform(MockMvcRequestBuilders.post("/union/face/orgOpenConfigEdit")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(JSON.toJSONString(organizeOpenConfig)))
.andExpect(status().isOk()) // 期待返回状态吗码200
.andDo(MockMvcResultHandlers.print())//打印调试结果到控制台
.andReturn()
.getResponse();//getResponse和andReturn是必须同时有的,如果要返回结果的话
}
}
Spring MVC的测试往往看似比较复杂。其实他的不同在于,他需要一个ServletContext来模拟我们的请求和响应。但是Spring也针对Spring MVC 提供了请求和响应的模拟测试接口,以方便我们的单元测试覆盖面不只是service,dao层。
2、代码解释:
方法解析:
- perform:执行一个RequestBuilder请求,会自动执行SpringMVC的流程并映射到相应的控制器执行处理;
- get:声明发送一个get请求的方法。MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables):根据uri模板和uri变量值得到一个GET请求方式的。另外提供了其他的请求的方法,如:post、put、delete等。
- param:添加request的参数,如上面发送请求的时候带上了了pcode = root的参数。假如使用需要发送json数据格式的时将不能使用这种方式,可见后面被@ResponseBody注解参数的解决方法
- andExpect:添加ResultMatcher验证规则,验证控制器执行完成后结果是否正确(对返回的数据进行的判断),在这里可以验证返回的结果是否正确,合理运用jsonPath可以对返回的对象进行处理,用“$.属性”获取里面的数据,如我要获取返回数据中的"configValue",可以写成"$.configValue"。
-
andExpect(jsonPath("$.configValue").value("53"))
上面代码中的value方法相当于
assertEquals("53",organizeOpenConfigBo.getConfigValue());
用哪种都可以。
- andDo:添加ResultHandler结果处理器,比如调试时打印结果到控制台(对返回的数据进行的判断);
- andReturn:最后返回相应的MvcResult;然后进行自定义验证/进行下一步的异步处理(对返回的数据进行的判断);
三、junit测试类生成插件教程
在idea中可以选择安装junit generator生成器,针对于想要生成测试方法的类,可以自动生成其测试方法类
安装方法如下:
因为我是已经安装过了,所以最后的红框里面是uninstall,没有安装的话应该是install的,懒得卸载再装了。
安装完插件后,重启idea
在想要生成测试类的代码空白处右键,选择Generate...然后选择Junit Test,Junit4
生成器就会根据模板生成这个类对应的空白测试代码了
注意:上面的模板生成路径和模板内容是可以配置的!!!!
下面是配置模板生成路径的方法,根据自己的需要调整生成代码的路径
如果对模板的内容不满意,也可以在生成测试类之前,对模板内容进行修改