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

简介: 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Jav...

 image.gif

image.gif

前言

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是认为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。本文将带大家介绍几款主流的单元测试使用方法,希望可以帮到大家。

公众号:「浅羽的IT小屋」

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

                                        • 测试
                                        @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();
                                        }

                                        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.gif

                                                          结语

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

                                                          image.gif


                                                          image.gif

                                                          点点点,一键三连都在这儿!

                                                          相关文章
                                                          |
                                                          6天前
                                                          |
                                                          数据库连接 Go 数据库
                                                          Go语言中的错误注入与防御编程。错误注入通过模拟网络故障、数据库错误等,测试系统稳定性
                                                          本文探讨了Go语言中的错误注入与防御编程。错误注入通过模拟网络故障、数据库错误等,测试系统稳定性;防御编程则强调在编码时考虑各种错误情况,确保程序健壮性。文章详细介绍了这两种技术在Go语言中的实现方法及其重要性,旨在提升软件质量和可靠性。
                                                          14 1
                                                          |
                                                          16天前
                                                          |
                                                          网络协议 关系型数据库 应用服务中间件
                                                          【项目场景】请求数据时测试环境比生产环境多花了1秒是怎么回事?
                                                          这是一位粉丝(谢同学)给V哥的留言,描述了他在优化系统查询时遇到的问题:测试环境优化达标,但生产环境响应时间多出1秒。通过抓包分析,发现MySQL请求和响应之间存在500毫秒的延迟,怀疑是网络传输开销。V哥给出了以下优化建议:
                                                          |
                                                          1月前
                                                          |
                                                          测试技术
                                                          自动化测试项目学习笔记(五):Pytest结合allure生成测试报告以及重构项目
                                                          本文介绍了如何使用Pytest和Allure生成自动化测试报告。通过安装allure-pytest和配置环境,可以生成包含用例描述、步骤、等级等详细信息的美观报告。文章还提供了代码示例和运行指南,以及重构项目时的注意事项。
                                                          197 1
                                                          自动化测试项目学习笔记(五):Pytest结合allure生成测试报告以及重构项目
                                                          |
                                                          1月前
                                                          |
                                                          测试技术 Python
                                                          自动化测试项目学习笔记(四):Pytest介绍和使用
                                                          本文是关于自动化测试框架Pytest的介绍和使用。Pytest是一个功能丰富的Python测试工具,支持参数化、多种测试类型,并拥有众多第三方插件。文章讲解了Pytest的编写规则、命令行参数、执行测试、参数化处理以及如何使用fixture实现测试用例间的调用。此外,还提供了pytest.ini配置文件示例。
                                                          31 2
                                                          |
                                                          1月前
                                                          |
                                                          测试技术 Python
                                                          自动化测试项目学习笔记(二):学习各种setup、tearDown、断言方法
                                                          本文主要介绍了自动化测试中setup、teardown、断言方法的使用,以及unittest框架中setUp、tearDown、setUpClass和tearDownClass的区别和应用。
                                                          63 0
                                                          自动化测试项目学习笔记(二):学习各种setup、tearDown、断言方法
                                                          |
                                                          1月前
                                                          |
                                                          人工智能 自动驾驶 机器人
                                                          【通义】AI视界|苹果自动驾驶汽车项目画上句号:加州测试许可被取消
                                                          本文精选了24小时内的重要科技新闻,包括Waymo前CEO批评马斯克对自动驾驶的态度、AMD发布新款AI芯片但股价波动、苹果造车项目终止、Familia.AI推出家庭应用以及AI逆向绘画技术的进展。更多内容请访问通义官网体验。
                                                          |
                                                          1月前
                                                          |
                                                          前端开发 JavaScript 应用服务中间件
                                                          linux安装nginx和前端部署vue项目(实际测试react项目也可以)
                                                          本文是一篇详细的教程,介绍了如何在Linux系统上安装和配置nginx,以及如何将打包好的前端项目(如Vue或React)上传和部署到服务器上,包括了常见的错误处理方法。
                                                          350 0
                                                          linux安装nginx和前端部署vue项目(实际测试react项目也可以)
                                                          |
                                                          1月前
                                                          |
                                                          Java Maven
                                                          Maven 项目测试
                                                          接下来我们要学习如何构建和测试这个项目。
                                                          42 5
                                                          |
                                                          1月前
                                                          |
                                                          JavaScript
                                                          vue尚品汇商城项目-day07【55.编码测试与打包发布项目】
                                                          vue尚品汇商城项目-day07【55.编码测试与打包发布项目】
                                                          31 3
                                                          |
                                                          2月前
                                                          |
                                                          设计模式 SQL 安全
                                                          PHP中的设计模式:单例模式的深入探索与实践在PHP的编程实践中,设计模式是解决常见软件设计问题的最佳实践。单例模式作为设计模式中的一种,确保一个类只有一个实例,并提供全局访问点,广泛应用于配置管理、日志记录和测试框架等场景。本文将深入探讨单例模式的原理、实现方式及其在PHP中的应用,帮助开发者更好地理解和运用这一设计模式。
                                                          在PHP开发中,单例模式通过确保类仅有一个实例并提供一个全局访问点,有效管理和访问共享资源。本文详细介绍了单例模式的概念、PHP实现方式及应用场景,并通过具体代码示例展示如何在PHP中实现单例模式以及如何在实际项目中正确使用它来优化代码结构和性能。
                                                          47 2
                                                          下一篇
                                                          无影云桌面