• EasyMock测试


    使用如下方式在Maven中添加EasyMock的依赖:

    Maven
    <dependency
          <groupId>org.easymock</groupId
          <artifactId>easymock</artifactId
          <version>3.2</version
          <scope>test</scope
        </dependency

    EasyMock使用动态代理实现模拟对象创建,其基本步骤为以下四步:

    以数据库应用为例的被测试代码如下:

    Code
    public class UserServiceImpl{ 
        private UserDao dao; 
        public User query(String id) throws Exception{ 
            try
        return dao.getById(id); 
    }catch(Exception e){ 
        throw e; 
    return null
       
    public class UserDao{ 
        public User getById(String id) throws Exception{ 
            try
        return ……; 
    }catch(Exception e){ 
        throw e; 
    return null

    现在希望对UserServiceImpl进行测试,而UserDao开发组只给出接口,尚未完成功能实现。

    使用Mock对UserDao进行模拟来测试UserServiceImpl。

    (1).基本的测试代码如下:

    Code
    public class UserServiceImplTest { 
           @Test 
           public void testQuery() { 
               User expectedUser = new User(); 
               user.setId(“1001”); 
               UserDao mock  = EasyMock.createMock(UserDao.class);//创建Mock对象 
               Easymock.expect(mock.getById("1001")).andReturn(expectedUser);//录制Mock对象预期行为 
               Easymock.replay(mock);//重放Mock对象,测试时以录制的对象预期行为代替真实对象的行为 
      
               UserServiceImpl  service = new UserServiceImpl(); 
               service.setUserDao(mock); 
               user user = service.query("1001");//调用测试方法 
               assertEquals(expectedUser, user); //断言测试结果  
               Easymock.verify(mock);//验证Mock对象被调用 
           
       }  

    注意:

    在EasyMock3.0之前,org.easymock.EasyMock使用JDK的动态代理实现Mock对象创建,因此只能针对接口进行Mock,org.easymock.classextension.EasyMock使用CGLIB动态代理创建Mock对象,可以针对普通类进行Mock。

    在EasyMock3.0之后,org.easymock.classextension.EasyMock被废弃,使用org.easymock.EasyMock可以针对接口和普通类进行Mock对象创建。

    (2).调用测试设定:

    如果想测试UserServiceImpl调用了UserDao的getById方法3次,则使用如下代码即可:

    Code
    Easymock.expect(mock.getById("1001")).andReturn(exceptUser).times(3);

    (3).方法异常:

    如果想测试UserServiceImpl在调用UserDao的getById方法时发生异常,可以使用如下代码:

    Code
    Easymock.expect(mock.getById("1001")).andThrow(new RuntimeException());

    在测试UserServiceImpl时就可以使用try-catch捕获Mock的异常。

    (4).基本参数匹配:

    上面的方法在Mock UserDao的getById方法时传入了“0001”的预期值,这种方式是精确参数匹配,如果UserServiceImpl在调用是传入的参数不是“0001”就会发生Unexpect method的Mock异常,可以使用下面的方法在Mock时进行参数匹配:

    Code
    Easymock.expect(mock.getById(Easymock.isA(String.class))).andReturn(exceptedUser).times(3);

    isA()方法会使用instanceof进行参数类型匹配,类似的方法还有anyInt(),anyObject(), isNull(),same(), startsWith()......

    (5).数组类型参数匹配:

    如果UserServiceImpl在调用UserDao的方法时传入的参数是数组,代码如下:

    Code
     public class UserServiceImpl{   
        private UserDao dao;   
        public List<String> queryNames(String[] ids) throws Exception{   
            try{   
        return dao.getNames(ids);   
    }catch(Exception e){   
        throw e;   
    }   
    return null;   
    }   
    }   
         
    public class UserDao{   
        public List<String> getNames(String[] ids) throws Exception{   
            try{   
        return ……;   
    }catch(Exception e){   
        throw e;   
    }   
    return null;   
    }   
     
    此时有两种办法来进行参数匹配:a.数组必须和测试给定的一致:
    [java] view plain copy
     
    Easymock.expect(mock.getNames(EasyMock.aryEq(testIds))).andReturn(exceptedNames);
     
     
    b.不考虑测试数组内容:[java] view plain copy
     
    Easymock.expect(mock.getNames(EasyMock.isA(String[].class))).andReturn(exceptedNames);
    Code
     (6).void方法Mock:如果要Mock的方法是无返回值类型,例子如下:
    [java] view plain copy
     
    public class UserDao { 
            public void updateUserById(String id) throws Exception{ 
                try
                update… 
            }catch(Exception e){ 
                throw e;  
            
            
        
     
     
    a.正常Mock代码如下:[java] view plain copy
     
    mock.updateUserById(“TestId”); 
    EasyMock.expectLastCall().anytimes(); 
     
     
    b.模拟发生异常的Mock代码如下:[java] view plain copy
     
    mock.updateUserById(“TestId”); 
    EasyMock.expectLastCall().andThrow(new RuntimeException()).anytimes(); 
     
     
    (7).多次调用返回不同值的Mock:对于迭代器类型的遍历代码来说,需要在不同调用时间返回不同的结果,以JDBC结果集为例代码如下:
    [java] view plain copy
     
    public List<String> getUserNames () throws Exception{ 
        List<String> usernames = new ArrayList<String>(); 
        ResultSet rs = pstmt.executeQuery(query); 
        try
            while(rs.next()){ 
                usernames.add(rs.getString(2)); 
            
        } catch (SQLException e) { 
            throw e; 
        
     
     
     
    在Mock结果集的next方法时如果总返回true,则代码就会陷入死循环,如果总返回false则代码逻辑根本无法执行到循环体内。正常的测试逻辑应该是先返回几次true执行循环体,然后在返回false退出循环,使用Mock可以方便模拟这种预期的行为,代码如下:
    [java] view plain copy
     
    EasyMock.expect(rs.next()).andReturn(true).times(2).andReturn(false).times(1); 
     
     
    更多的关于EasyMock的用法,请参考EasyMock官方文档:
  • 相关阅读:
    Net EF框架+ MySql示例
    Net EF框架+ MySql示例
    C#中读写INI配置文件
    C#中读写INI配置文件
    C#中读写INI配置文件
    IntelliJ IDEA 常用快捷键和设置
    IntelliJ IDEA 常用快捷键和设置
    C++STL_max
    出错啦!
    枝晶生长的宏微观模型
  • 原文地址:https://www.cnblogs.com/xinziyublog/p/5650996.html
Copyright © 2020-2023  润新知