写点什么

告别祈祷式编程|单元测试在项目里的正确落地姿势

作者:浅羽技术
  • 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) (测试:期望出现某一类异常)
复制代码


image.gif


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)));
复制代码


image.gif


「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开始
复制代码


image.gif



  • 一般匹配符


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) ) );      断言符合条件之一,相当于“或”(||)
复制代码


image.gif



  • ‍‍‍‍数值相关匹配符


‍‍‍‍  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
复制代码


image.gif



  • 集合相关匹配符


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
复制代码


image.gif


4、Suit 的使用

「需求:」


  • 现在有 30 个实体,每个 DAO 和每个 Service 都编写了测试用例。所以至少有 60 个测试类,当我们开发一个功能的时候,我们需要检测当前开发好的功能是否影响了其他已经开发好的功能,这个时候需要运行这 60 个测试用例,只有所有的测试用例都没有问题,才确定当前开发的功能对其他功能是没有影响的


  • 这个时候就需要运用 Suit,Suit 的作用就是可以一次性的运行多个测试用例


@RunWith(Suite.class)   //表示的是使用什么类来运行@Suite.SuiteClasses({TestCaltureB.class,TestCaltureA.class})  //这个表示的是要运行哪些类public class TestCaltureAB {}
复制代码


image.gif


5、Stub(装)的使用

「解决的问题:」


  • 假设两个人做开发,一个人做的是 DAO,另外一个人做的是 Service,现在的问题是 DAO 层还没有来得及开发,只是有约束规范(只有接口没有实现),现在是 Service 层需要测试,那怎么办呢?


  • Stub 的思想就是:自己编写 DAO 的实现类使用 Map 集合来模拟数据库的数据以及访问的这个过程,就叫做 Stub


「具体使用:」


  • 首先声明 DAO 的接口


public interface IUserDAO {    /**     * 通过id找用户     * @param userId     * @return     */    User getUserById(Serializable userId);}
复制代码


image.gif



  • 编写 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;    }}
复制代码


image.gif



  • 编写 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);    }}
复制代码


image.gif



  • 编写测试的类


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;    }}
复制代码


image.gif


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")));    }
复制代码


image.gif



  • 备份一张表


/** * 备份一张表的数据 */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")));}
复制代码


image.gif



  • 插入测试数据


/** * 插入准备好的数据到数据库 */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);}
复制代码


image.gif



  • 测试


@Testpublic 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();}
复制代码


image.gif



  • 还原这个数据


/** * 还原数据库的数据 */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);}
复制代码


image.gif



  • 整体代码如下:


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")));    }}
复制代码


image.gif



  • 编写测试的基类


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);    }}
复制代码


image.gif



  • 使用基类来完成测试


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();    }}
复制代码


image.gif


7、EasyMock 的使用

「使用场景:」

dbunit是专门用来测试DAO层的EasyMock是专门用来测试Service层的DAO层的测试的重点:数据的准确性Service层测试的重点是DAO的调用次数、DAO层的调用的顺序EasyMocK的适用场景:就是当Service开发好之后 DAO层还没有来得及开发的时候 Service层需要测试
复制代码


image.gif



  • 第一个案例


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);    }}
复制代码


image.gif



  • 关于这个的高级应用


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();    }}
复制代码


image.gif


8、SpringTest 的使用

「简介:」


  • 整合了 Junit4 框架,来做单元测试


「具体使用:」


  • 编写基类


@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {"classpath:bean-base.xml"})public class AbstractSpringTestCase {}
复制代码


image.gif



  • 测试


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());    }}
复制代码


结语

本篇关于单元测试的主流框架以及工具的介绍就先到这里结束了,后续会出更多关于单元测试系列文章,谢谢大家支持!

image


发布于: 刚刚阅读数: 5
用户头像

浅羽技术

关注

才疏学浅,习习而为,编程羽录,与你同行。 2019-02-26 加入

分享一些计算机信息知识、理论技术、工具资源、软件介绍、后端开发、面试、工作感想以及生活随想等一系列文章。

评论

发布
暂无评论
告别祈祷式编程|单元测试在项目里的正确落地姿势_Java_浅羽技术_InfoQ写作社区