看到一篇很是好的关于Springboot单元测试的文章,特此转过来,原文地址: Spring Boot干货系列:(十二)Spring Boot使用单元测试
此次来介绍下Spring Boot中对单元测试的整合使用,本篇会经过如下4点来介绍,基本知足平常需求java
Spring Boot中引入单元测试很简单,依赖以下:程序员
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
在生成的测试类中就能够写单元测试了。用spring自带spring-boot-test的测试工具类便可,spring-boot-starter-test 启动器能引入这些 Spring Boot 测试模块:web
Spring Boot中单元测试类写在在src/test/java目录下,你能够手动建立具体测试类,若是是IDEA,则能够经过IDEA自动建立测试类,以下图,也能够经过快捷键⇧⌘T
(MAC)或者Ctrl+Shift+T
(Window)来建立,以下:spring
自动生成测试类以下:json
而后再编写建立好的测试类,具体代码以下:springboot
package com.dudu.service; import com.dudu.domain.LearnResource; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import static org.hamcrest.CoreMatchers.*; @RunWith(SpringRunner.class) @SpringBootTest public class LearnServiceTest { @Autowired private LearnService learnService; @Test public void getLearn(){ LearnResource learnResource=learnService.selectByKey(1001L); Assert.assertThat(learnResource.getAuthor(),is("嘟嘟MD独立博客")); } }
上面就是最简单的单元测试写法,顶部只要@RunWith(SpringRunner.class)
和SpringBootTest
便可,想要执行的时候,鼠标放在对应的方法,右键选择run该方法便可。网络
RunWith解释session
@RunWith就是一个运行器,如 @RunWith(SpringJUnit4ClassRunner.class),让测试运行于Spring测试环境,@RunWith(SpringJUnit4ClassRunner.class)使用了Spring的SpringJUnit4ClassRunner,以便在测试开始的时候自动建立Spring的应用上下文。其余的想建立spring容器的话,就得子啊web.xml配置classloder。 注解了@RunWith就能够直接使用spring容器,直接使用@Test注解,不用启动spring容器
测试用例中我使用了assertThat断言,下文中会介绍,也推荐你们使用该断言。mvc
上面只是针对Service层作测试,可是有时候须要对Controller层(API)作测试,这时候就得用到MockMvc了,你能够没必要启动工程就能测试这些接口。app
MockMvc实现了对Http请求的模拟,可以直接使用网络的形式,转换到Controller的调用,这样可使得测试速度快、不依赖网络环境,并且提供了一套验证的工具,这样可使得请求的验证统一并且很方便。
Controller类:
package com.dudu.controller; /** 教程页面 * Created by tengj on 2017/3/13. */ @Controller @RequestMapping("/learn") public class LearnController extends AbstractController{ @Autowired private LearnService learnService; private Logger logger = LoggerFactory.getLogger(this.getClass()); @RequestMapping("") public String learn(Model model){ model.addAttribute("ctx", getContextPath()+"/"); return "learn-resource"; } /** * 查询教程列表 * @param page * @return */ @RequestMapping(value = "/queryLeanList",method = RequestMethod.POST) @ResponseBody public AjaxObject queryLearnList(Page<LeanQueryLeanListReq> page){ List<LearnResource> learnList=learnService.queryLearnResouceList(page); PageInfo<LearnResource> pageInfo =new PageInfo<LearnResource>(learnList); return AjaxObject.ok().put("page", pageInfo); } /** * 新添教程 * @param learn */ @RequestMapping(value = "/add",method = RequestMethod.POST) @ResponseBody public AjaxObject addLearn(@RequestBody LearnResource learn){ learnService.save(learn); return AjaxObject.ok(); } /** * 修改教程 * @param learn */ @RequestMapping(value = "/update",method = RequestMethod.POST) @ResponseBody public AjaxObject updateLearn(@RequestBody LearnResource learn){ learnService.updateNotNull(learn); return AjaxObject.ok(); } /** * 删除教程 * @param ids */ @RequestMapping(value="/delete",method = RequestMethod.POST) @ResponseBody public AjaxObject deleteLearn(@RequestBody Long[] ids){ learnService.deleteBatch(ids); return AjaxObject.ok(); } /** * 获取教程 * @param id */ @RequestMapping(value="/resource/{id}",method = RequestMethod.GET) @ResponseBody public LearnResource qryLearn(@PathVariable(value = "id") Long id){ LearnResource lean= learnService.selectByKey(id); return lean; } }
这里咱们也自动建立一个Controller的测试类,具体代码以下:
package com.dudu.controller; import com.dudu.domain.User; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpSession; import org.springframework.test.context.junit4.SpringRunner; 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.result.MockMvcResultMatchers; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; @RunWith(SpringRunner.class) @SpringBootTest public class LearnControllerTest { @Autowired private WebApplicationContext wac; private MockMvc mvc; private MockHttpSession session; @Before public void setupMockMvc(){ mvc = MockMvcBuilders.webAppContextSetup(wac).build(); //初始化MockMvc对象 session = new MockHttpSession(); User user =new User("root","root"); session.setAttribute("user",user); //拦截器那边会判断用户是否登陆,因此这里注入一个用户 } /** * 新增教程测试用例 * @throws Exception */ @Test public void addLearn() throws Exception{ String json="{\"author\":\"HAHAHAA\",\"title\":\"Spring\",\"url\":\"http://tengj.top/\"}"; mvc.perform(MockMvcRequestBuilders.post("/learn/add") .accept(MediaType.APPLICATION_JSON_UTF8) .content(json.getBytes()) //传json参数 .session(session) ) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()); } /** * 获取教程测试用例 * @throws Exception */ @Test public void qryLearn() throws Exception { mvc.perform(MockMvcRequestBuilders.get("/learn/resource/1001") .contentType(MediaType.APPLICATION_JSON_UTF8) .accept(MediaType.APPLICATION_JSON_UTF8) .session(session) ) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.jsonPath("$.author").value("嘟嘟MD独立博客")) .andExpect(MockMvcResultMatchers.jsonPath("$.title").value("Spring Boot干货系列")) .andDo(MockMvcResultHandlers.print()); } /** * 修改教程测试用例 * @throws Exception */ @Test public void updateLearn() throws Exception{ String json="{\"author\":\"测试修改\",\"id\":1031,\"title\":\"Spring Boot干货系列\",\"url\":\"http://tengj.top/\"}"; mvc.perform(MockMvcRequestBuilders.post("/learn/update") .accept(MediaType.APPLICATION_JSON_UTF8) .content(json.getBytes())//传json参数 .session(session) ) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()); } /** * 删除教程测试用例 * @throws Exception */ @Test public void deleteLearn() throws Exception{ String json="[1031]"; mvc.perform(MockMvcRequestBuilders.post("/learn/delete") .accept(MediaType.APPLICATION_JSON_UTF8) .content(json.getBytes())//传json参数 .session(session) ) .andExpect(MockMvcResultMatchers.status().isOk()) .andDo(MockMvcResultHandlers.print()); } }
上面实现了基本的增删改查的测试用例,使用MockMvc的时候须要先用MockMvcBuilders使用构建MockMvc对象,以下
@Before public void setupMockMvc(){ mvc = MockMvcBuilders.webAppContextSetup(wac).build(); //初始化MockMvc对象 session = new MockHttpSession(); User user =new User("root","root"); session.setAttribute("user",user); //拦截器那边会判断用户是否登陆,因此这里注入一个用户 }
由于拦截器那边会判断是否登陆,因此这里我注入了一个用户,你也能够直接修改拦截器取消验证用户登陆,先测试完再开启。
这里拿一个例子来介绍一下MockMvc简单的方法
/** * 获取教程测试用例 * @throws Exception */ @Test public void qryLearn() throws Exception { mvc.perform(MockMvcRequestBuilders.get("/learn/resource/1001") .contentType(MediaType.APPLICATION_JSON_UTF8) .accept(MediaType.APPLICATION_JSON_UTF8) .session(session) ) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.jsonPath("$.author").value("嘟嘟MD独立博客")) .andExpect(MockMvcResultMatchers.jsonPath("$.title").value("Spring Boot干货系列")) .andDo(MockMvcResultHandlers.print()); }
application/json;charset=UTF-8
application/json;charset=UTF-8
嘟嘟MD独立博客
,不是就测试不经过本例子测试以下:
JUnit 4.4 结合 Hamcrest 提供了一个全新的断言语法——assertThat。程序员能够只使用 assertThat 一个断言语句,结合 Hamcrest 提供的匹配符,就能够表达所有的测试思想,咱们引入的版本是Junit4.12因此支持assertThat。
清单 1 assertThat 基本语法
assertThat( \[value\], \[matcher statement\] );
清单 2 使用匹配符 Matcher 和不使用之间的比较
// 想判断某个字符串 s 是否含有子字符串 "developer" 或 "Works" 中间的一个 // JUnit 4.4 之前的版本:assertTrue(s.indexOf("developer")>-1||s.indexOf("Works")>-1 ); // JUnit 4.4: assertThat(s, anyOf(containsString("developer"), containsString("Works"))); // 匹配符 anyOf 表示任何一个条件知足则成立,相似于逻辑或 "||", 匹配符 containsString 表示是否含有参数子 // 字符串,文章接下来会对匹配符进行具体介绍
优势 3:assertThat 再也不像 assertEquals 那样,使用比较难懂的“谓宾主”语法模式(如:assertEquals(3, x);),相反,assertThat 使用了相似于“主谓宾”的易读语法模式(如:assertThat(x,is(3));),使得代码更加直观、易读。
注:本篇博文为转载,原问地址:Spring Boot干货系列:(十二)Spring Boot使用单元测试