Jmockit使用指南

概述mock对象这个虚拟的对象就是mock对象。mock对象就是真实对象在调试期间的代替品。
摘要由CSDN通过智能技术生成

概述

mock对象


虚拟的对象就是mock对象。mock对象就是真实对象在调试期间的代替品。

关于什么时候需要Mock对象,Tim Mackinnon给我们了一些建议:

真实对象具有不可确定的行为(产生不可预测的结果,如股票的行情)

真实对象很难被创建(比如具体的web容器)

真实对象的某些行为很难触发(比如网络错误)

真实情况令程序的运行速度很慢

真实对象有用户界面

 测试需要询问真实对象它是如何被调用的(比如测试可能需要验证某个回调函数是否被调用了)

真实对象实际上并不存在(当需要和其他开发小组,或者新的硬件系统打交道的时候,这是一个普遍的问题)


比如以下场景:

1. mock掉外部依赖的应用的HSF service的调用,比如uic,tp 的hsf服务依赖。


2. 对DAO层(访问mysql、oracle、tair、tfs等底层存储)的调用mock等。


3. 对系统间异步交互notify消息的mock。


4. 对method_A里面调用到的method_B 的mock 。


5. 对一些应用里面自己的 class(abstract, final, static),interface,annotation ,enum,native等的mock。


Mock工具的原理:

1. record阶段:录制期望。也可以理解为数据准备阶段。创建依赖的class 或interface或method ,模拟返回的数据,及调用的次数等。


2. replay阶段:通过调用被测代码,执行测试。期间会invoke 到 第一阶段record的mock对象或方法。


3. verify阶段:验证。可以验证调用返回是否正确。及mock的方法调用次数,顺序等。

利用JMockit工具来编写基于行为的测试代码,通常符合下面的经典模板:

import mockit.*;  
... other imports ...  
   
public class SomeTest  
{  
   //  零个或者更多的mock 属性, 这些属性对于整个类的所有测试方法来说是通用的。  
   @Mocked Collaborator mockCollaborator;  
   @NonStrict AnotherDependency anotherDependency;  
   ...  
   
   @Test  
   public void testWithRecordAndReplayOnly(mock parameters)  
   {  
      // 如果这里需要测试前的准备,可以在这里执行,但对于Jmockit 来说,对此没特别要求。当然这里也可以为空。  
   
      new Expectations() // 一个期望块  
      {  
         // 零个或者多个局部 mock 属性域  
   
         {  
            //  一个或者多个mock对象(类型)的调用,这些调用会被Expectations记录(Recorded)下来  
            //一些没有被mock的方法、对象类型等同样可以在这个期望块里面调用  
         }  
      };  
   
      // 单元测试代码真正业务逻辑在此执行  
   
      // 如果需要,可以在这里进行验证代码编写,当然可以利用JUnit/TestNG 断言  
   }  
   
   @Test  
   public void testWithReplayAndVerifyOnly(mock parameters)  
   {  
      // 如果这里需要测试前的准备,可以在这里执行,但对于Jmockit 来说,对此没特别要求。当然这里也可以为空。  
   
      // 单元测试代码真正业务逻辑在此执行  
   
      new Verifications() {
  { // 一个验证块  
          //  一个或者多个mock对象(类型)的调用,这些调用用于验证结果是否正确  
            //一些没有被mock的方法、对象类型等同样可以在这个验证块里面调用  
      }};  
   
      // 如果需求,这里可以添加其他额外的验证代码,  
     //  当然,这些验证可以编写在这里,也可以在Verifications块之前  
   }  
   
   @Test  
   public void testWithBothRecordAndVerify(mock parameters)  
   {  
      //如果这里需要测试前的准备,可以在这里执行,但对于Jmockit 来说,对此没特别要求。当然这里也可以为空。  
   
      new NonStrictExpectations() { // 同样是一个期望块  
         //零个或者多个局部 mock 属性域  
         {  
            // 一个或者多个mock对象(类型)的调用,这些调用会被Expectations记录(Recorded)下来  
         }  
      };  
   
      // 单元测试代码真正业务逻辑在此执行  
   
      new VerificationsInOrder() {
  { // 同样是一个验证块  
         // 一个或者多个mock对象(类型)的调用,这些调用将期望按照特定的顺序进行比较。  
      }};  
   
     // 如果需求,这里可以添加其他额外的验证代码,  
     //  当然,这些验证可以编写在这里,也可以在Verifications块之前  
   }  


Jmockit的简介:

 Jmockit可以mock的种类包含了:
        1.class(abstract, final, static) ;
        2.interface ;
        3.enum ;
        4.annotation ;
        5.native 。


 Jmockit 两种mock的方式:


一.根据用例的测试路径,测试代码内部逻辑Behavior-oriented(Expectations & Verifications) 

        对于这种情景,可以使用jmockit的基于行为的mock方式。目的是从被测代码的使用角度出发,结合数据的输入输出来检验程序运行的这个正确性。使用这个方式,需要把被依赖的代码mock掉,实际上相当于改变了被依赖的代码的逻辑。通常在集成测试中,如果有难以调用的外部接口,就通过这个方式mock掉,模拟外部接口。 这种方式有点像黑盒测试。


二.根据测试用例的输入输出数据,测试代码是否功能运行正常。State-oriented(MockUp<GenericType>)  

        对于这种情景,可以使用jmockit基于状态的mock方式。在这种方式中,目的是测试单元测试及其依赖代码的调用过程,验证代码逻辑是否满足测试路径。  由于被依赖代码可能在自己单测中已测试过,或者难以测试,就需要把这些被依赖代码的逻辑用预定期待的行为替换掉,也就是mock掉,从而把待测是代码隔离开,这也是单元测试的初衷。 这种方式和白盒测试接近。


通俗点讲,Behavior-oriented是基于行为的mock,对mock目标代码的行为进行模仿,更像黑盒测试。State-oriented 是基于状态的mock,是站在目标测试代码内部的。可以对传入的参数进行检查、匹配,才返回某些结果,类似白盒。而State-oriented的 new MockUp基本上可以mock任何代码或逻辑。非常强大。

JMockit元素

@Tested和@Injectable: 

对@Tested对象判断是否为null,是则通过合适构造器初始化,并实现依赖注入。调用构造方法时,会尝试使用@Injectable的字段进行构造器注入。普通注入时,@Injectable字段如果没有在测试方法前被赋值,其行为将会被mock成默认值(静态方法和构造函数不会被mock掉)。Injectable最大作用除了注入,还有就是mock的范围只限当前注释实例。一句话:@Injectable的实例会自动注入到@Tested中,如果没初始赋值,那么JMockit将会以相应规则初始化。

@Mocked:

@Mocked修饰的实例,将会把实例对应类的所有实例的所有行为都mock掉(无论构造方法,还是private,protected方法,够霸气吧)。在Expectation区块中,声明的成员变量均默认带有@Mocked,@Mocked会mock掉所有方法,如果某些函数我们不希望它也被mock,可以通过methods="methodName"来设置被mock的类只对methodName方法进行mock。或者通过Expectation构造函数传入Class对象或Instance对象,这样只会区块内Class或Instance对应的行为进行mock。

比如:

  @Test  
    public void behaviorTest_fail3time() {  
               
        new Expectations() {        // Expectations中包含的内部类区块中,体现的是一个录制被测类的逻辑。  
            @Mocked(methods="tryIt")  // 表明被修饰的类对tryIt()方法进行mock。  
            Guess g;  
            {  
                g.tryIt();             // 期待调用Guess.tryIt()方法  
                result = false;        // mock掉返回值为false(表明猜不中)  
                t
  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值