告别祈祷式编程|单元测试在项目里的正确落地姿势
- 2023-04-20 江苏
本文字数:12015 字
阅读完需:约 39 分钟
前言
单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如 C 语言中单元指一个函数,Java 里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是认为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。本文将带大家介绍几款主流的单元测试使用方法,希望可以帮到大家。
1、为什么要使用单元测试?
「好处:」
可以使用单元测试来完成模块功能的一个测试
使用单元测试可以更好的完成模块的回归测试
「在开发中一般要进行如下测试:」
单元测试:一般情况下就是完成我们模块功能的一个检测
回归测试:当我们开发好一个功能之后,这个功能是否会影响其他已经开发好的这个功能
集成测试:简单的说就是项目开发完成的时候,这个所有功能是否完整,以及功能之间是否存在 bug
公测:进行公测
2、Junit 的使用
「简介:」
Junit 是单元测试框架工具,在项目开发中是经常用到的,利用 Junit4 进行单元测试非常简单方便,所以熟悉 Junit 是很有必要的
「主要用法:」
@Before //初始化数据用的
@BeforeClass //初始化数据用的(只是执行一次)
@After //对象销毁的时候用的
@AfterClass //对象销毁的时候用的(只是执行一次)
@Test(expected=xxx.class、timeout=5000) (测试:期望出现某一类异常)
3、Hamcrest 的使用(Junit 的一个补充)
「使用原因:」
使用过 Junit 的应该有体验:在实际开发中,一些基本的断言,如 equal,null,true 它们的可读性并不是很好。而且很多时候我们要比较对象、集合、Map 等数据结构。这样我们要进行大段的字段获取再断言。或者干脆自己编写表达式并断言其结果
Junit4.4 引入了 Hamcrest 框架,Hamcrest 提供了一套匹配符,这些匹配符更接近自然语言,可读性高,更加灵活
需求:假设说加法的上面,加上一个不为 null 的一个断言,这个时候就出现了两个断言,这时候你就需要写两次,有没有办法只写一次呢?有
//使用这个Hamcrest来进行断言
// Assert.assertThat(result, IsNull.notNullValue());
// AllOf:所有的条件都要成立才表示校验成功
// AnyOf:一个条件校验成功那么才表示的是校验成功
// IsEqual:相等
// IsInstanceOf:这个就表示判定的是对象是否是某一个类的对象
// IsNot:不是某一个类的对象
// IsNull:判断空值
// StringEndWith:以什么结尾
// StringStartsWith:这个表示的是以什么开始
// SubStringMatcher:截取的字符串和谁匹配
// Assert.assertThat(result, AllOf.allOf(IsNull.notNullValue(), IsEqual.equalTo(30)));
// Assert.assertThat(result, AnyOf.anyOf(IsNull.notNullValue(), IsEqual.equalTo(30)));
「Unit4 新断言-Hamcrest 的常用方法:」
字符相关匹配符
1、equalTo:
assertThat(testedValue, equalTo(expectedValue));
断言被测的testedValue等于expectedValue,equalTo可以断言数值之间,字符串之间和对象之间是否相等,相当于Object的equals方法
2、equalToIgnoringCase:
assertThat(testedString, equalToIgnoringCase(expectedString));
断言被测的字符串testedString在忽略大小写的情况下等于expectedString
3、equalToIgnoringWhiteSpace:
assertThat(testedString, equalToIgnoringWhiteSpace(expectedString);
断言被测的字符串testedString在忽略头尾的任意个空格的情况下等于expectedString
(注意:字符串中的空格不能被忽略)
4、containsString:
assertThat(testedString, containsString(subString) );
断言被测的字符串testedString包含子字符串subString
5、endsWith:
assertThat(testedString, endsWith(suffix));
断言被测的字符串testedString以子字符串suffix结尾
6、startsWith:
assertThat(testedString, startsWith(prefix));
断言被测的字符串testedString以子字符串prefix开始
一般匹配符
1、nullValue():
assertThat(object,nullValue());
断言被测object的值为null
2、notNullValue():
assertThat(object,notNullValue());
断言被测object的值不为null
3、is:
assertThat(testedString, is(equalTo(expectedValue)));
断言被测的object等于后面给出匹配表达式
1)is匹配符简写应用之一:
assertThat(testedValue, is(expectedValue));
is(equalTo(x))的简写,断言testedValue等于expectedValue
2)is匹配符简写应用之二:
assertThat(testedObject, is(Cheddar.class));
is(instanceOf(SomeClass.class))的简写,断言testedObject为Cheddar的实例
4、not:
assertThat(testedString, not(expectedString));
与is匹配符正好相反,断言被测的object不等于后面给出的object
5、allOf:
assertThat(testedNumber, allOf( greaterThan(8), lessThan(16) ) );
断言符合所有条件,相当于“与”(&&)
6、anyOf:
assertThat(testedNumber, anyOf( greaterThan(16), lessThan(8) ) );
断言符合条件之一,相当于“或”(||)
数值相关匹配符
1、closeTo:
assertThat(testedDouble, closeTo( 20.0, 0.5 ));
断言被测的浮点型数testedDouble在20.0-0.5 ~ 20.0+0.5范围之内
2、greaterThan:
assertThat(testedNumber, greaterThan(16.0));
断言被测的数值testedNumber大于16.0
3、lessThan:
assertThat(testedNumber, lessThan (16.0));
断言被测的数值testedNumber小于16.0
4、greaterThanOrEqualTo:
assertThat(testedNumber, greaterThanOrEqualTo (16.0));
断言被测的数值testedNumber大于等于16.0
5、lessThanOrEqualTo:
assertThat(testedNumber, lessThanOrEqualTo (16.0));
断言被测的testedNumber小于等于16.0
集合相关匹配符
1、hasEntry:
assertThat(mapObject, hasEntry("key", "value" ) );
断言被测的Map对象mapObject含有一个键值为"key"对应元素值为"value"的Entry项
2、hasItem:
assertThat(iterableObject, hasItem (element));
表明被测的迭代对象iterableObject含有元素element项则测试通过
3、hasKey:
assertThat(mapObject, hasKey ("key"));
断言被测的Map对象mapObject含有键值“key”
4、hasValue:
assertThat(mapObject, hasValue(value));
断言被测的Map对象mapObject含有元素值value
4、Suit 的使用
「需求:」
现在有 30 个实体,每个 DAO 和每个 Service 都编写了测试用例。所以至少有 60 个测试类,当我们开发一个功能的时候,我们需要检测当前开发好的功能是否影响了其他已经开发好的功能,这个时候需要运行这 60 个测试用例,只有所有的测试用例都没有问题,才确定当前开发的功能对其他功能是没有影响的
这个时候就需要运用 Suit,Suit 的作用就是可以一次性的运行多个测试用例
@RunWith(Suite.class) //表示的是使用什么类来运行
@Suite.SuiteClasses({TestCaltureB.class,TestCaltureA.class}) //这个表示的是要运行哪些类
public class TestCaltureAB {
}
5、Stub(装)的使用
「解决的问题:」
假设两个人做开发,一个人做的是 DAO,另外一个人做的是 Service,现在的问题是 DAO 层还没有来得及开发,只是有约束规范(只有接口没有实现),现在是 Service 层需要测试,那怎么办呢?
Stub 的思想就是:自己编写 DAO 的实现类使用 Map 集合来模拟数据库的数据以及访问的这个过程,就叫做 Stub
「具体使用:」
首先声明 DAO 的接口
public interface IUserDAO {
/**
* 通过id找用户
* @param userId
* @return
*/
User getUserById(Serializable userId);
}
编写 Service 的实现类
public class UserService {
public IUserDAO userDAO=null;
public void setUserDAO(IUserDAO userDAO) {
this.userDAO = userDAO;
}
/**
* 通过id找用户
* @param userId
* @return
*/
public User getUserById(Serializable userId){
User user=userDAO.getUserById(userId);
return user;
}
}
编写 Stub 的 DAO 的实现类
public class UserDAOStub implements IUserDAO{
//使用map集合来模拟我们的数据库
private Map<Integer,User> users=new HashMap<>();
public UserDAOStub() {
for (int i=0;i< 10;i++){
users.put(i+1,new User(i+1,i+1+"",i+1+""));
}
}
@Override
public User getUserById(Serializable userId) {
return users.get(userId);
}
}
编写测试的类
public class TestUserService {
private UserService userService=null;
private User exUser=null;
@Before
public void init(){
userService=new UserService();
exUser=new User();
//期望返回的的这个用户对象
exUser.setPassword("1");
exUser.setUserId(1);
exUser.setUserName("1");
UserDAOStub userDAOStub = new UserDAOStub();
userService.setUserDAO(userDAOStub);
}
@Test
public void testGetUserById(){
User user=userService.getUserById(1);
//接下来就进行断言了
Assert.assertEquals(exUser.getUserId(),user.getUserId());
Assert.assertEquals(exUser.getPassword(),user.getPassword());
Assert.assertEquals(exUser.getUserName(),user.getUserName());
}
@After
public void close(){
userService=null;
}
}
6、dbunit 的使用
「主要用途:」
dbunit 是专门用来测试 DAO 层的,以后开发中 DAO 的测试就可以使用 dbunit 来进行
「使用流程:」
备份所有的表
private void backAllTable() throws SQLException, IOException, DataSetException {
//第一步:获取连接上的dataSet对象
IDataSet dataSet = conn.createDataSet();
//第二步:将数据进行备份
//使用属性来描述要备份的这个数据
// FlatXmlDataSet.write(dataSet,new FileOutputStream(new File("G:/allTable.xml")));
//使用节点来描述要备份的这个数据
XmlDataSet.write(dataSet, new FileOutputStream(new File("G:/allTable1.xml")));
}
备份一张表
/**
* 备份一张表的数据
*/
private void backOneTable() throws DataSetException, IOException {
//创建一个查询的DataSet对象
QueryDataSet dataSet = new QueryDataSet(conn);
//第二步:添加要备份的表名
dataSet.addTable("t_user");
//第三步:进行备份
FlatXmlDataSet.write(dataSet, new FileOutputStream(new File("G:/allTable.xml")));
}
插入测试数据
/**
* 插入准备好的数据到数据库
*/
private void insertDataTable() throws DatabaseUnitException, SQLException {
//获取插入数据的DataSet对象
IDataSet dataSet = new FlatXmlDataSet(new FlatXmlProducer(new InputSource(TestUserDAO.class.getClassLoader().getResourceAsStream("table.xml"))));
DatabaseOperation.CLEAN_INSERT.execute(conn, dataSet);
}
测试
@Test
public void testFindUserById() throws SQLException, IOException, DatabaseUnitException {
backOneTable();
insertDataTable();
// 编写测试代码的地方
User acUser=userDAO.findUserById(78); //实际返回的用户对象
//下一步:进行断言
Assert.assertEquals(exUser.getUserId(),acUser.getUserId());
Assert.assertEquals(exUser.getUserName(),acUser.getUserName());
Assert.assertEquals(exUser.getPassword(),acUser.getPassword());
//还原数据库的数据
resumeTable();
}
还原这个数据
/**
* 还原数据库的数据
*/
private void resumeTable() throws IOException, DatabaseUnitException, SQLException {
//备份数据的DataSet对象
IDataSet dataSet=new FlatXmlDataSet(new InputSource(new FileInputStream(new File("G:/allTable.xml"))));
DatabaseOperation.CLEAN_INSERT.execute(conn,dataSet);
}
整体代码如下:
package com.qy.dbunit;
import com.qy.utils.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.dbunit.DatabaseUnitException;
import org.dbunit.database.AmbiguousTableNameException;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.QueryDataSet;
import org.dbunit.dataset.DataSetException;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.dataset.xml.FlatXmlProducer;
import org.dbunit.dataset.xml.XmlDataSet;
import org.dbunit.operation.DatabaseOperation;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.xml.sax.InputSource;
import java.io.*;
import java.sql.SQLException;
/**
* @Auther: qianyu
* @Date: 2020/11/17 10:02
* @Description:
*/
public class TestUserDAO {
//维护的是用户的DAO的对象
private UserDAO userDAO=null;
//实例化dbunit中的这个数据库的连接
private DatabaseConnection conn = null;
//期望返回的用户对象值
private User exUser=null;
@Before
public void init() throws Exception {
conn = new DatabaseConnection(JdbcUtils.getConnection());
exUser=new User();
exUser.setUserId(78);
exUser.setUserName("78");
exUser.setPassword("78");
userDAO=new UserDAO();
}
/**
* 第一步:对数据库的数据进行备份
* 备份一张表的数据
* 备份整个数据库中的数据
* 第二步:插入提前准备好的测试数据
* 第三步:测试
* 第四步:将数据库的数据清空
* 第五步:还原数据库的数据
*/
@Test
public void testFindUserById() throws SQLException, IOException, DatabaseUnitException {
backOneTable();
insertDataTable();
// 编写测试代码的地方
User acUser=userDAO.findUserById(78); //实际返回的用户对象
//下一步:进行断言
Assert.assertEquals(exUser.getUserId(),acUser.getUserId());
Assert.assertEquals(exUser.getUserName(),acUser.getUserName());
Assert.assertEquals(exUser.getPassword(),acUser.getPassword());
//还原数据库的数据
resumeTable();
}
/**
* 还原数据库的数据
*/
private void resumeTable() throws IOException, DatabaseUnitException, SQLException {
//备份数据的DataSet对象
IDataSet dataSet=new FlatXmlDataSet(new InputSource(new FileInputStream(new File("G:/allTable.xml"))));
DatabaseOperation.CLEAN_INSERT.execute(conn,dataSet);
}
/**
* 插入准备好的数据到数据库
*/
private void insertDataTable() throws DatabaseUnitException, SQLException {
//获取插入数据的DataSet对象
IDataSet dataSet = new FlatXmlDataSet(new FlatXmlProducer(new InputSource(TestUserDAO.class.getClassLoader().getResourceAsStream("table.xml"))));
DatabaseOperation.CLEAN_INSERT.execute(conn, dataSet);
}
/**
* 备份数据库中所有表中的数据
*/
private void backAllTable() throws SQLException, IOException, DataSetException {
//第一步:获取连接上的dataSet对象
IDataSet dataSet = conn.createDataSet();
//第二步:将数据进行备份
//使用属性来描述要备份的这个数据
// FlatXmlDataSet.write(dataSet,new FileOutputStream(new File("G:/allTable.xml")));
//使用节点来描述要备份的这个数据
XmlDataSet.write(dataSet, new FileOutputStream(new File("G:/allTable1.xml")));
}
/**
* 备份一张表的数据
*/
private void backOneTable() throws DataSetException, IOException {
//创建一个查询的DataSet对象
QueryDataSet dataSet = new QueryDataSet(conn);
//第二步:添加要备份的表名
dataSet.addTable("t_user");
//第三步:进行备份
FlatXmlDataSet.write(dataSet, new FileOutputStream(new File("G:/allTable.xml")));
}
}
编写测试的基类
package com.qy.base;
import org.apache.commons.dbutils.QueryRunner;
import org.dbunit.DatabaseUnitException;
import org.dbunit.database.AmbiguousTableNameException;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.QueryDataSet;
import org.dbunit.dataset.DataSetException;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.operation.DatabaseOperation;
import org.xml.sax.InputSource;
import java.io.*;
import java.sql.Connection;
import java.sql.SQLException;
/**
* @Auther: qianyu
* @Date: 2020/11/17 10:58
* @Description:
*/
public class AbstractDbunitTestCase implements Serializable{
//dbunit的这个连接
private DatabaseConnection conn=null;
//传入测试数据的dataSet对象
private IDataSet dataSetTest=null;
//创建一个临时文件
private File temFile=null;
public AbstractDbunitTestCase(Connection connection,IDataSet dataSetTest) throws DatabaseUnitException {
conn=new DatabaseConnection(connection);
this.dataSetTest=dataSetTest;
}
/**
* 备份多张表的数据
* @param tabNames
*/
public void backManyTable(String ... tabNames) throws DataSetException, IOException {
QueryDataSet queryDataSet=new QueryDataSet(conn);
for (int i=0;i<tabNames.length;i++){
queryDataSet.addTable(tabNames[i]);
}
temFile=File.createTempFile("table",".xml");
//进行备份
FlatXmlDataSet.write(queryDataSet,new FileOutputStream(temFile));
}
/**
* 备份一张表
* @param tableName
*/
public void backOneTable(String tableName) throws IOException, DataSetException {
backManyTable(tableName);
}
/**
* 插入测试数据
*/
public void insertTestData() throws DatabaseUnitException, SQLException {
DatabaseOperation.CLEAN_INSERT.execute(conn,dataSetTest);
}
/**
* 还原这个表的数据
*/
public void resumeTable() throws IOException, DatabaseUnitException, SQLException {
IDataSet dataSet=new FlatXmlDataSet(new InputSource(new FileInputStream(temFile)));
DatabaseOperation.CLEAN_INSERT.execute(conn,dataSet);
}
}
使用基类来完成测试
package com.qy.dbunit;
import com.qy.base.AbstractDbunitTestCase;
import com.qy.utils.JdbcUtils;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.xml.sax.InputSource;
import java.sql.SQLException;
/**
* @Auther: qianyu
* @Date: 2020/11/17 11:12
* @Description:
*/
public class TestUserDAO1 extends AbstractDbunitTestCase {
private UserDAO userDAO=null;
//期望返回的用户对象值
private User exUser=null;
public TestUserDAO1() throws Exception {
super(JdbcUtils.getConnection(),new FlatXmlDataSet(new InputSource(TestUserDAO1.class.getClassLoader().getResourceAsStream("table.xml"))));
}
@Before
public void init() throws Exception {
exUser=new User();
exUser.setUserId(78);
exUser.setUserName("78");
exUser.setPassword("79");
userDAO=new UserDAO();
backOneTable("t_user");
insertTestData();
}
@Test
public void testFindUserById() throws SQLException {
// 编写测试代码的地方
User acUser=userDAO.findUserById(78); //实际返回的用户对象
//下一步:进行断言
Assert.assertEquals(exUser.getUserId(),acUser.getUserId());
Assert.assertEquals(exUser.getUserName(),acUser.getUserName());
Assert.assertEquals(exUser.getPassword(),acUser.getPassword());
}
@After
public void destory() throws Exception {
resumeTable();
}
}
7、EasyMock 的使用
「使用场景:」
dbunit是专门用来测试DAO层的
EasyMock是专门用来测试Service层的
DAO层的测试的重点:数据的准确性
Service层测试的重点是DAO的调用次数、DAO层的调用的顺序
EasyMocK的适用场景:就是当Service开发好之后 DAO层还没有来得及开发的时候 Service层需要测试
第一个案例
public class TestUserService {
private UserService userService=null;
private User exUser=null;
@Before
public void init(){
userService=new UserService();
exUser=new User();
exUser.setUserId(1);
exUser.setUserName("浅羽");
exUser.setPassword("123");
}
/**
* 有返回值的情况
*/
@Test
public void testFindUserById(){
//第一步:使用EasyMock生成接口的实现类
IUserDAO userDAO=EasyMock.createMock(IUserDAO.class);
//第二步:进行记录
//下面表示的意思是调用了上面对象的哪一个方法传递,某一个值的时候 希望的返回值是什么?
EasyMock.expect(userDAO.findUserById(1)).andReturn(exUser);
EasyMock.expect(userDAO.findUserById(1)).andReturn(exUser);
//第三步:进行replay(使能:使上面的设置生效)
EasyMock.replay(userDAO);
//第四步:进行设置
userService.setUserDAO(userDAO);
//第五步:进行测试
userService.findUserById(1);
//第六步:进行校验
EasyMock.verify(userDAO);
}
/**
* 没有返回值的情况
*/
@Test
public void testSave(){
IUserDAO userDAO=EasyMock.createMock(IUserDAO.class);
//没有返回值的情况
//第一步:调用(记录中的调用)
userDAO.save();
//第二步:告诉他没有返回值
EasyMock.expectLastCall();
//第一步:调用(记录中的调用)
userDAO.save();
//第二步:告诉他没有返回值
EasyMock.expectLastCall();
//第一步:调用(记录中的调用)
userDAO.save();
//第二步:告诉他没有返回值
EasyMock.expectLastCall();
//使能
EasyMock.replay(userDAO);
//设置
userService.setUserDAO(userDAO);
//调用
userService.save();
//校验
EasyMock.verify(userDAO);
}
/**
* 测试有参数和没有参数混用的情况
* 注意:即时改变了顺序 只要你记录了都不会报错(非严格意义上的Mock)
*
*/
@Test
public void testDelete(){
IUserDAO userDAO=EasyMock.createMock(IUserDAO.class);
//进行记录
//记录第一个调用
EasyMock.expect(userDAO.findUserById(1)).andReturn(exUser);
//记录第二个调用
userDAO.delete();
EasyMock.expectLastCall();
//第三个:使能
EasyMock.replay(userDAO);
//设置
userService.setUserDAO(userDAO);
//调用
userService.delete(1);
//校验
EasyMock.verify(userDAO);
}
/**
* 这个玩的是有严格顺序的Mock
* 严格意义上的Mock对调用的顺序都有联系
*/
@Test
public void testDelete1(){
IUserDAO userDAO=EasyMock.createStrictMock(IUserDAO.class);
//进行记录
//记录第一个调用
EasyMock.expect(userDAO.findUserById(1)).andReturn(exUser);
//记录第二个调用
userDAO.delete();
EasyMock.expectLastCall();
//第三个:使能
EasyMock.replay(userDAO);
//设置
userService.setUserDAO(userDAO);
//调用
userService.delete(1);
//校验
EasyMock.verify(userDAO);
}
}
关于这个的高级应用
public class TestABService {
private ABService abService=null;
@Before
public void init(){
abService=new ABService();
}
/**
* 测试顺序的问题
*/
@Test
public void testMM(){
//创建实现类
A a=EasyMock.createStrictMock(A.class);
B b=EasyMock.createStrictMock(B.class);
//进行记录
a.a();
EasyMock.expectLastCall();
a.b();
EasyMock.expectLastCall();
b.c();
EasyMock.expectLastCall();
b.d();
EasyMock.expectLastCall();
//使能
EasyMock.replay(a,b);
//设置
abService.setA(a);
abService.setB(b);
//调用
abService.mm();
//进行认证
EasyMock.verify(a,b);
}
@Test
public void testMMM(){
IMocksControl strictControl = EasyMock.createStrictControl();
A a=strictControl.createMock(A.class);
B b=strictControl.createMock(B.class);
//进行记录
a.a();
EasyMock.expectLastCall();
a.b();
EasyMock.expectLastCall();
b.c();
EasyMock.expectLastCall();
b.d();
EasyMock.expectLastCall();
//使能
strictControl.replay();
//设置
abService.setA(a);
abService.setB(b);
//调用
abService.mm();
//进行认证
strictControl.verify();
}
@Test
public void testMM1(){
IMocksControl strictControl = EasyMock.createStrictControl();
A a=strictControl.createMock(A.class);
B b=strictControl.createMock(B.class);
//进行记录
a.a();
EasyMock.expectLastCall();
a.b();
EasyMock.expectLastCall();
b.c();
EasyMock.expectLastCall();
b.d();
EasyMock.expectLastCall();
//使能
strictControl.replay();
//设置
abService.setA(a);
abService.setB(b);
//调用
abService.mm();
//进行认证
strictControl.verify();
}
}
8、SpringTest 的使用
「简介:」
整合了 Junit4 框架,来做单元测试
「具体使用:」
编写基类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:bean-base.xml"})
public class AbstractSpringTestCase {
}
测试
public class TestUserDAO extends AbstractSpringTestCase {
@Autowired
private UserDAO userDAO;
private User exUser=null;
@Before
public void init(){
exUser=new User(1,"浅羽","123");
}
@Test
public void testFindUserById(){
User acUser= userDAO.findUserById(1);
//断言
//下一步:进行断言
Assert.assertEquals(exUser.getUserId(),acUser.getUserId());
Assert.assertEquals(exUser.getUserName(),acUser.getUserName());
Assert.assertEquals(exUser.getPassword(),acUser.getPassword());
}
}
结语
本篇关于单元测试的主流框架以及工具的介绍就先到这里结束了,后续会出更多关于单元测试系列文章,谢谢大家支持!
版权声明: 本文为 InfoQ 作者【浅羽技术】的原创文章。
原文链接:【http://xie.infoq.cn/article/1cc537c995079272039e330a8】。文章转载请联系作者。
浅羽技术
才疏学浅,习习而为,编程羽录,与你同行。 2019-02-26 加入
分享一些计算机信息知识、理论技术、工具资源、软件介绍、后端开发、面试、工作感想以及生活随想等一系列文章。
评论