现实问题: 在实际的面向对象软件设计中,我们经常会碰到这样的情况,我们在对现实对象进行构建之后,对象之间是通过一系列的接口来实现。这在面向对象设计里是最自然不过的事情了,但是随着软件测试需求的发展,这会产生一些小问题。举个例子,用户A现在拿到一个用户B提供的接口,他根据这个接口实现了自己的需求,但是用户A编译自己的代码后,想简单模拟测试一下,怎么办呢?这点也是很现实的一个问题。我们是否可以针对这个接口来简单实现一个代理类,来测试模拟,期望代码生成自己的结果呢?Mock对象就源于此。
模型:
现在有两个公司,公司A,B是专门从事中间件开发的,但是两者的侧重点不同。假如公司A是专门从事算法实现的,公司B是专门从事界面设计的。一开始,两个公司都已经约好了一个相同的规范,这个规范是固定下来的(也就是接口),然后两个公司自己独立实现相应的具体内容。过了一段时间后,公司B在开发的过程中,想测试一下界面的显示如何,但是公司A的算法还没有完成,那么他该怎么办呢?这里公司B也知道,他提供一个特别数字进去,接口立刻就会返回一个确认的数字,一些简单的确定性结果是知道的。公司B想进行这些测试的话,他不得不根据这些接口写一些简单的代码来代替,这样进行重复的工作有点麻烦。幸好他们都是使用Java来进行规范约定的,他们了解到有一个easymock的类库支持这方面的测试。
底层相关技术:
让我们来回忆一下,如果用户使用C++和java的程序的生成,C++在最后的阶段还需要连接才能生成一个整体程序,这在灵活性与java源代码的机制是不能比的(java的各个类是独立的,打包的那些类也是独立的,只有在加载进去才进行连接,这在代码被加载进去的时候,我们还可以执行很多的动作,如插入一些相关的业务需求,这也是AOP的一个焦点,javassit代码库的实现类似于这)。所以用java实现Mock对象是很简单的,这里我就介绍一下easymock来说明一下这些测试。
一个样例:
1)准备知识: 了解JUnit框架,easymock,
下载地址
2)样例测试平台: eclipse3.1(默认需要配有JUnit)
3)说明:使用easymock的好处是, 你不需要添加额外的开发环境,他完全是基于JUnit的,因此在eclipse中测试和JUnit的测试方法一样,编写好相关的代码后, RunAs-> JUnitTest就行了。
4)代码实现:
i 首先是公司AB约定的算法接口
// $Id: Calculator.java 2006-4-22 14:17:46 $
package easymock2.samples;
/**
* @author Sidney J.Yellow(Sidney.J.Yellow@gmail.com)
*/
public interface Calculator {
int add(int a,int b);
int sub(int a,int b);
}
ii公司B现在完成了他的展示界面,里面使用到这个接口的加法运算:
// $Id: Show.java 2006-4-22 14:21:32 $
package easymock2.samples;
/**
* @author Sidney J.Yellow(Sidney.J.Yellow@gmail.com)
*/
public class Show {
private Calculator calculator;
public Calculator getCalculator() {
return calculator;
}
public void setCalculator(Calculator calculator) {
this.calculator = calculator;
}
public void show(){
int a=10,b=12;
System.out.println("10+12="+calculator.add(a,b));
}
}
iii 现在公司B想测试一下这个界面是否会打印出22这个结果,他该怎么办呢?他想出了一个办法,就是使用easymock来进行简单的测试:
// $Id: ShowTest.java 2006-4-22 14:24:54 $
package easymock2.samples;
import junit.framework.TestCase;
import static org.easymock.EasyMock.*;
/**
* @author Sidney J.Yellow(Sidney.J.Yellow@gmail.com)
*/
public class ShowTest extends TestCase {
private Calculator calculator_mock;
private Show show;
@Override
protected void setUp() throws Exception {
calculator_mock=createMock(Calculator.class); //使用EasyMock创建了一个Mock对象
show=new Show();
show.setCalculator(calculator_mock); //使用mock对象
super.setUp();
}
public void testShow(){ //测试show方法
//在Show当中我们使用了a,b是10,12,我们希望mock对象会返回22
calculator_mock.add(10,12);
expectLastCall().andReturn(22); //我们希望公司A提供的算法会返回22
//注意,我们这里没有提高add的方法的具体实现,我们只是会认为10+12会返回22。
replay(calculator_mock);
//设置期望值后,我们开始调用公司B的show方法,看是否会出错
//公司B的show方法里面调用了add方法,提供了参数10和12,控制台会打印出22
show.show();
}
}
iv 测试成功,控制台输出: 10+12=22
当然,easymock还提供了其他更加多的简单操作,这里只是从mock测试的需求上来介绍一下,详细请参考官方文档。
小结:
使用mock对象,我们在单元测试方面做得更加完善,在一些依赖性很强的相关类中,也可以进行单元测试,最终使软件更加健全。
感谢你的阅读!
对这篇文章有什么疑问的话,请联系作者。作者联系地址:
Sidney.J.Yellow@gmail.com