详解Spring Boot实战之单元测试
本文介绍使用spring测试框架提供的mockmvc对象,对restful api进行单元测试
spring测试框架提供mockmvc对象,可以在不需要客户端-服务端请求的情况下进行mvc测试,完全在服务端这边就可以执行controller的请求,跟启动了测试服务器一样。
测试开始之前需要建立测试环境,setup方法被@before修饰。通过mockmvcbuilders工具,使用webapplicationcontext对象作为参数,创建一个mockmvc对象。
mockmvc对象提供一组工具函数用来执行assert判断,都是针对web请求的判断。这组工具的使用方式是函数的链式调用,允许程序员将多个测试用例链接在一起,并进行多个判断。在这个例子中我们用到下面的一些工具函数:
perform(get(...))建立web请求。在我们的第三个用例中,通过mockmvcrequestbuilder执行get请求。
andexpect(...)可以在perform(...)函数调用后多次调用,表示对多个条件的判断,这个函数的参数类型是resultmatcher接口,在mockmvcresultmatchers这这个类中提供了很多返回resultmatcher接口的工具函数。这个函数使得可以检测同一个web请求的多个方面,包括http响应状态码(response status),响应的内容类型(content type),会话中存放的值,检验重定向、model或者header的内容等等。这里需要通过第三方库json-path检测json格式的响应数据:检查json数据包含正确的元素类型和对应的值,例如jsonpath("$.name").value("中文测试")用于检查在根目录下有一个名为name的节点,并且该节点对应的值是“testuser”。
本文对rest api的开发不做详细描述,如需了解可以参考 spring boot实战之rest接口开发及数据库基本操作
1、修改pom.xml,添加依赖库json-path,用于检测json格式的响应数据
<dependency> <groupid>com.jayway.jsonpath</groupid> <artifactid>json-path</artifactid> </dependency>
2、添加用户数据模型userinfo.java
package com.xiaofangtech.sunt.bean; import javax.persistence.entity; import javax.persistence.generatedvalue; import javax.persistence.generationtype; import javax.persistence.id; import javax.persistence.table; import javax.validation.constraints.size; @entity @table(name="t_userinfo") public class userinfo { @id @generatedvalue(strategy = generationtype.auto) private long id; @size(min=0, max=32) private string name; private integer age; @size(min=0, max=255) private string address; public long getid() { return id; } public void setid(long id) { this.id = id; } public string getname() { return name; } public void setname(string name) { this.name = name; } public integer getage() { return age; } public void setage(integer age) { this.age = age; } public string getaddress() { return address; } public void setaddress(string address) { this.address = address; } }
3、添加控制器usercontroller.java,用于实现对用户的增删改查
package com.xiaofangtech.sunt.controller; import java.util.list; import org.springframework.beans.factory.annotation.autowired; import org.springframework.data.jpa.repository.modifying; 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.restcontroller; import com.xiaofangtech.sunt.bean.userinfo; import com.xiaofangtech.sunt.repository.userinforepository; import com.xiaofangtech.sunt.utils.*; @restcontroller @requestmapping("user") public class usercontroller { @autowired private userinforepository userrepositoy; /*** * 根据用户id,获取用户信息 * @param id * @return */ @requestmapping(value="getuser", method=requestmethod.get) public object getuser(long id) { userinfo userentity = userrepositoy.findone(id); resultmsg resultmsg = new resultmsg(resultstatuscode.ok.geterrcode(), resultstatuscode.ok.geterrmsg(), userentity); return resultmsg; } /*** * 获取所有用户列表 * @return */ @requestmapping(value="getalluser", method=requestmethod.get) public object getuserlist() { list<userinfo> userentities = (list<userinfo>) userrepositoy.findall(); resultmsg resultmsg = new resultmsg(resultstatuscode.ok.geterrcode(), resultstatuscode.ok.geterrmsg(), userentities); return resultmsg; } /*** * 新增用户信息 * @param userentity * @return */ @modifying @requestmapping(value="adduser", method=requestmethod.post) public object adduser(@requestbody userinfo userentity) { userrepositoy.save(userentity); resultmsg resultmsg = new resultmsg(resultstatuscode.ok.geterrcode(), resultstatuscode.ok.geterrmsg(), userentity); return resultmsg; } /*** * 更新用户信息 * @param userentity * @return */ @modifying @requestmapping(value="updateuser", method=requestmethod.put) public object updateuser(@requestbody userinfo userentity) { userinfo user = userrepositoy.findone(userentity.getid()); if (user != null) { user.setname(userentity.getname()); user.setage(userentity.getage()); user.setaddress(userentity.getaddress()); userrepositoy.save(user); } resultmsg resultmsg = new resultmsg(resultstatuscode.ok.geterrcode(), resultstatuscode.ok.geterrmsg(), user); return resultmsg; } /*** * 删除用户 * @param id * @return */ @modifying @requestmapping(value="deleteuser", method=requestmethod.delete) public object deleteuser(long id) { try { userrepositoy.delete(id); } catch(exception exception) { } resultmsg resultmsg = new resultmsg(resultstatuscode.ok.geterrcode(), resultstatuscode.ok.geterrmsg(), null); return resultmsg; } }
4、修改测试类,添加对以上接口进行单元测试的测试用例
package com.xiaofangtech.sunt; 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.springapplicationconfiguration; import org.springframework.http.mediatype; import org.springframework.test.context.junit4.springjunit4classrunner; import org.springframework.test.context.web.webappconfiguration; import org.springframework.test.web.servlet.mockmvc; import org.springframework.test.web.servlet.setup.mockmvcbuilders; import org.springframework.web.context.webapplicationcontext; import com.fasterxml.jackson.databind.objectmapper; import com.xiaofangtech.sunt.bean.userinfo; import static org.springframework.test.web.servlet.request.mockmvcrequestbuilders.*; import static org.springframework.test.web.servlet.result.mockmvcresultmatchers.*; import static org.hamcrest.matchers.*; //这是junit的注解,通过这个注解让springjunit4classrunner这个类提供spring测试上下文。 @runwith(springjunit4classrunner.class) //这是spring boot注解,为了进行集成测试,需要通过这个注解加载和配置spring应用上下 @springapplicationconfiguration(classes = springjunittestapplication.class) @webappconfiguration public class springjunittestapplicationtests { @autowired private webapplicationcontext context; private mockmvc mockmvc; @before public void setupmockmvc() throws exception { mockmvc = mockmvcbuilders.webappcontextsetup(context).build(); } /*** * 测试添加用户接口 * @throws exception */ @test public void testadduser() throws exception { //构造添加的用户信息 userinfo userinfo = new userinfo(); userinfo.setname("testuser2"); userinfo.setage(29); userinfo.setaddress("北京"); objectmapper mapper = new objectmapper(); //调用接口,传入添加的用户参数 mockmvc.perform(post("/user/adduser") .contenttype(mediatype.application_json_utf8) .content(mapper.writevalueasstring(userinfo))) //判断返回值,是否达到预期,测试示例中的返回值的结构如下{"errcode":0,"errmsg":"ok","p2pdata":null} .andexpect(status().isok()) .andexpect(content().contenttype(mediatype.application_json_utf8)) //使用jsonpath解析返回值,判断具体的内容 .andexpect(jsonpath("$.errcode", is(0))) .andexpect(jsonpath("$.p2pdata", notnullvalue())) .andexpect(jsonpath("$.p2pdata.id", not(0))) .andexpect(jsonpath("$.p2pdata.name", is("testuser2"))); } /*** * 测试更新用户信息接口 * @throws exception */ @test public void testupdateuser() throws exception { //构造添加的用户信息,更新id为2的用户的用户信息 userinfo userinfo = new userinfo(); userinfo.setid((long)2); userinfo.setname("testuser"); userinfo.setage(26); userinfo.setaddress("南京"); objectmapper mapper = new objectmapper(); mockmvc.perform(put("/user/updateuser") .contenttype(mediatype.application_json_utf8) .content(mapper.writevalueasstring(userinfo))) //判断返回值,是否达到预期,测试示例中的返回值的结构如下 //{"errcode":0,"errmsg":"ok","p2pdata":null} .andexpect(status().isok()) .andexpect(content().contenttype(mediatype.application_json_utf8)) .andexpect(jsonpath("$.errcode", is(0))) .andexpect(jsonpath("$.p2pdata", notnullvalue())) .andexpect(jsonpath("$.p2pdata.id", is(2))) .andexpect(jsonpath("$.p2pdata.name", is("testuser"))) .andexpect(jsonpath("$.p2pdata.age", is(26))) .andexpect(jsonpath("$.p2pdata.address", is("南京"))); } /*** * 测试根据用户id获取用户信息接口 * @throws exception */ @test public void testgetuser() throws exception { mockmvc.perform(get("/user/getuser?id=2")) .andexpect(status().isok()) .andexpect(content().contenttype(mediatype.application_json_utf8)) .andexpect(jsonpath("$.errcode", is(0))) .andexpect(jsonpath("$.p2pdata", notnullvalue())) .andexpect(jsonpath("$.p2pdata.id", is(2))) .andexpect(jsonpath("$.p2pdata.name", is("testuser"))) .andexpect(jsonpath("$.p2pdata.age", is(26))) .andexpect(jsonpath("$.p2pdata.address", is("南京"))); } /*** * 测试获取用户列表接口 * @throws exception */ @test public void testgetusers() throws exception { mockmvc.perform(get("/user/getalluser")) .andexpect(status().isok()) .andexpect(content().contenttype(mediatype.application_json_utf8)) .andexpect(jsonpath("$.errcode", is(0))) .andexpect(jsonpath("$.p2pdata", notnullvalue())); } }
5、运行测试,执行junit test
一共执行4个测试用例,全都通过
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
下一篇: 感觉