JMock测试框架—自动化测试主流工具(4)

发表于:2020-5-21 11:50

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:51Testing教研团队    来源:51Testing软件测试网原创

  3.4 JMock测试框架
  JMock是用于创建Mock对象的工具框架,它基于Java开发,在Java测试与开发环境中有不可比拟的优势。更重要的是,JMock大大简化了虚拟对象的使用。
  3.4.1 驱动和桩
  3.3节讲到了驱动和桩,那么究竟什么是驱动呢?这个很好理解,测试夹具就是驱动。那么什么是桩呢?桩有何价值呢?
  举一个简单的例子,一个简单的程序有3个函数,即A、B、C,函数的调用关系为A→B→C,那么现在要测试函数C,只需要写一个驱动去调用C即可。那么如果要测试B呢?驱动肯定要有。另外,为了使B测试时不受C的影响,需要隔离C,那么怎么隔离呢?用桩C#代替C,让B调用C#而不是C。而C#桩是可以由测试人员来控制的,想让它返回什么结果就返回什么结果,这样就可以达到隔离的效果。
  再考虑另外一种场景,现在要对B函数进行测试,但是C函数还没有实现。毫无疑问,若B函数是无法运行的,测试必然无法正常进行。那么怎么办?写一个桩——C##,伪装成C好像已经实现,这样B就可以成功运行,从而达到测试目的。
  例如,StringHandle类中的isNumber方法还没有实现,那么可以采用这种方法来实现isNumber,代码如图3-36所示。
   public boolean isNumber(String source) {
     return true;
  }
  图3-36 关于isNumber的示例
  以上代码完全可以让调用isNumber的代码运行起来,不过这里有一个比较严重的问题:将开发的代码更改了,强行在StringHandle类中加入了一个“伪装”的isNumber方法。这显然会有问题,测试人员不能通过修改开发的原始代码来达到测试目的。另外,通常被测代码不一定是源代码,有可能是打包好的JAR包,调用JAR包中的接口来进行测试,这个时候是没有办法改变代码的,那么究竟如何处理,才能从根本上解决这一问题呢?答案是使用Mock对象。
  3.4.2 Mock对象
  顾名思义,Mock对象用来假冒一个方法,达到隔离环境的目的,适用于对一些还没有实现的方法的模拟。其实,只要真正理解了“多态”的使用,使用Mock对象就不会有任何问题,所以Mock的核心在于“多态”。下面基于多态特性来介绍Mock对象。
  要使用Mock,必须借助多态性。同样,要使用多态性,必须借助接口。显然,之前并没有使用任何接口来定义规范,而直接使用类方法来完成。所以,需要对StringHandle类进行适当改造,让它可以实现多态性。为了对比改造后与改造前的区别,建议新建一个包,专门存放改造后的代码,在此创建一个新的包com.learn.updated,将com.learn.compare目录下的所有源代码复制过来。
  首先,定义IString接口,定义方法isNumber,代码如图3-37所示。
   package com.learn.updated;

  public interface IString {
     public boolean isNumber(String source);
  }
  图3-37 定义接口和方法
  然后,把StringHandle类改造成实现IString接口的实现类,代码如图3-38所示。
   package com.learn.updated;

  import Java.io.BufferedReader;
  import Java.io.IOException;
  import Java.io.InputStreamReader;
  图3-38 改造类
   import Java.util.Arrays;
  import Java.util.Vector;
  public class StringHandle {
  public IString istring;    // 定义接口变量istring
  // 从控制台输入字符串
  public Integer[] inputString() {
  // 代码不变,此处省略
  }
  // 将字符串解析成数组
  public Integer[] splitString(String source, String delimiter) {
  Vector<Integer> vector = new Vector<Integer>();
  int position = source.indexOf(delimiter);
  while (source.contains(delimiter)) {
  String value = source.substring(0, position);
  if (istring.isNumber(value)) {    // 将该行修改成istring.isNumber
  vector.add(Integer.parseInt(value));
  }
  else {
  Integer[] result = {1};
  return result;
  }
  source = source.substring(position + 1, source.length());
  position = source.indexOf(delimiter);
  }
  vector.add(Integer.parseInt(source));
  Integer[] array = new Integer[vector.size()];
  vector.copyInto(array);
  return array;
  }
  // 检查字符串是否可正常转换为数字
  public boolean isNumber(String source) {
  // 删除该方法
  }
  }
  图3-38 改造类(续)
  以上代码的核心在于使用istring来调用其方法isNumber,而不是直接通过this.isNumber调用,这样就可以通过将不同的实例传递给istring来实现Mock的方法。
  接下来,创建一个新的包com.learn.jmock,并创建一个Mock类MockIString.Java,代码如图3-39所示。
   package com.learn.jmock;
  import com.learn.updated.*;
  public class MockIString implements IString {
  图3-39 创建包和类
   public boolean isNumber(String source) {
       return true;
  }
 }
  图3-39 创建包和类(续)
  最后,使用Mock对象来对StringHandle.splitString进行测试,具体代码(StringHandle- Mock.Java)如图3-40所示。
   package com.learn.jmock;
  import static org.junit.Assert.assertArrayEquals;
  import org.junit.Test;
  import com.learn.updated.StringHandle;
  public class StringHandleMock {
  @Test
  public void splitString() {
  StringHandle stringHandle = new StringHandle();
  stringHandle.istring = new MockIString();
  String source = "333,111,222,666";
  Integer[] expect = {333, 111, 222, 666};
  Integer[] actual = stringHandle.splitString(source, ",");
  assertArrayEquals(expect, actual);
  }
  }
  图3-40 进行测试的具体代码
  上述代码通过了测试,虽然看到StringHandle中并没有实现isNumber,但是由于在MockIString中实现了它,利用多态性将MockIString的实例传递给StringHandle类的istring接口变量,这样splitString方法就可以正常使用istring.isNumber了。这样做并不会修改到被测试的源代码,从根本上解决了使用桩所遇到的各种问题。
  Mock对象的使用范畴如下。
  ●真实对象具有不可确定的行为,产生不可预测的效果(如股票行情、天气预报)。
  ●真实对象很难创建。
  ●真实对象的某些行为很难触发。
  ●真实对象实际上还不存在(和其他开发小组或者新的硬件交互)等。
  使用Mock对象测试的关键步骤如下。
  (1)使用一个接口来描述这个对象。
  (2)在产品代码中实现这个接口。
  (3)在测试代码中实现这个接口。
  在被测代码中只通过接口来引用对象,所以代码不知道引用的对象是真实对象还是Mock对象。

版权声明:51Testing软件测试网获得人民邮电出版社和作者授权连载本书部分章节。
任何个人或单位未获得明确的书面许可,不得对本文内容复制、转载或进行镜像,否则将追究法律责任。
100家互联网大公司java笔试题汇总,填问卷领取~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号