码迷,mamicode.com
首页 > 编程语言 > 详细

Java单元测试进阶之如何打桩(用easymock轻松打桩)

时间:2014-07-09 15:05:44      阅读:470      评论:0      收藏:0      [点我收藏+]

标签:des   blog   http   java   使用   art   

打桩(mock)是单元测试的重要内容和难点,学好打桩的技术,做单元测试基本就没什么困难了。 

       mock有两种,一种是静态的,一种是动态的。静态的就是在写测试代码之前根据需要打桩的类生成另外一个类,这个类就是mock object。动态的就是mock object是在测试代码运行的时候才生成的。所以很明显,动态打桩比静态打桩要方便地多。本章就是介绍动态打桩的工具。

        早期的动态mock工具只能够mock接口,而不能够mock类;现在的mock工具无论是mock接口还是类都能够轻松完成了。

        easymock就是其中的佼佼者,easymock现在已经是2.2版本了,本文使用的是easymock1.2_Java1.5版本。使用easymock能够轻松的mock任何接口,但如果想mock类,那还需要另外一个lib,就是easymockclassextension,使用了这个工具,你就能轻松地mock你要的任何类了。本文使用的是easymockclassextension1.2,使用这个库必须要cglib这个jar包,而cglib又需要asm的jar包,所以要搭建好环境还得花些时间,不过当你把环境搞好之后,你便会发现物超所值,从此以后打桩无难事了。cglib和asm的版本一定要适配,要不然不能正常工作,幸好cglib的网站已经提供了cglib和asm的绑定包,本文所用的是cglib-nodep-2.2_beta1版本。

        本章先对如何对接口进行打桩示例,下一章再对如何对接口进行打桩示例。

先看欲打桩接口代码:

 

bubuko.com,布布扣/************************************************************
bubuko.com,布布扣 * Project Name: lhjTest
bubuko.com,布布扣 * File Name   : CoolInterface.java
bubuko.com,布布扣 * File Desc   : CoolInterface.java
bubuko.com,布布扣 * Author      : Administrator
bubuko.com,布布扣 * Create      : 2007-3-25
bubuko.com,布布扣 * Modify:
bubuko.com,布布扣 ***********************************************************/
bubuko.com,布布扣package org.lhj.cool.junit;
bubuko.com,布布扣
bubuko.com,布布扣/**
bubuko.com,布布扣 * @author Administrator
bubuko.com,布布扣 */
bubuko.com,布布扣public interface CoolInterface
bubuko.com,布布扣{
bubuko.com,布布扣    String reverseString(String inputStr) throws NullPointerException;
bubuko.com,布布扣}
bubuko.com,布布扣

 

该接口很简单,只要一个reverString的方法。

下面看看欲测试类(使用了CoolInterface)的代码:

 

bubuko.com,布布扣/************************************************************
bubuko.com,布布扣 * Project Name: lhjTest
bubuko.com,布布扣 * File Name   : UseCoolInterface.java
bubuko.com,布布扣 * File Desc   : UseCoolInterface.java
bubuko.com,布布扣 * Author      : Administrator
bubuko.com,布布扣 * Create      : 2007-3-25
bubuko.com,布布扣 * Modify:
bubuko.com,布布扣 ***********************************************************/
bubuko.com,布布扣package org.lhj.cool.mock;
bubuko.com,布布扣
bubuko.com,布布扣import org.lhj.cool.junit.CoolInterface;
bubuko.com,布布扣
bubuko.com,布布扣/**
bubuko.com,布布扣 * @author Administrator
bubuko.com,布布扣 */
bubuko.com,布布扣public class UseCoolInterface
bubuko.com,布布扣{
bubuko.com,布布扣    private CoolInterface cool;
bubuko.com,布布扣    
bubuko.com,布布扣    public void setCoolInterface(CoolInterface cool)
bubuko.com,布布扣    {
bubuko.com,布布扣        this.cool = cool;
bubuko.com,布布扣    }
bubuko.com,布布扣    
bubuko.com,布布扣    public String reverseString(String inputStr) throws NullPointerException
bubuko.com,布布扣    {
bubuko.com,布布扣        return cool.reverseString(inputStr);
bubuko.com,布布扣    }
bubuko.com,布布扣
bubuko.com,布布扣}
bubuko.com,布布扣

 

这个类也很简单,相当于一个adapter。

下面看看如何使用easymock进行接口的打桩:

 

bubuko.com,布布扣/************************************************************
bubuko.com,布布扣 * Project Name: lhjTest
bubuko.com,布布扣 * File Name   : UseCoolInterfaceJTest.java
bubuko.com,布布扣 * File Desc   : UseCoolInterfaceJTest.java
bubuko.com,布布扣 * Author      : Administrator
bubuko.com,布布扣 * Create      : 2007-3-25
bubuko.com,布布扣 * Modify:
bubuko.com,布布扣 ***********************************************************/
bubuko.com,布布扣package org.lhj.cool.mock;
bubuko.com,布布扣
bubuko.com,布布扣import junit.framework.TestCase;
bubuko.com,布布扣
bubuko.com,布布扣import org.easymock.MockControl;
bubuko.com,布布扣import org.lhj.cool.junit.CoolInterface;
bubuko.com,布布扣import org.lhj.cool.mock.UseCoolInterface;
bubuko.com,布布扣
bubuko.com,布布扣/**
bubuko.com,布布扣 * @author Administrator
bubuko.com,布布扣 */
bubuko.com,布布扣public class UseCoolInterfaceJTest extends TestCase
bubuko.com,布布扣{
bubuko.com,布布扣    private UseCoolInterface testInterface;
bubuko.com,布布扣    
bubuko.com,布布扣    private MockControl ctrl;
bubuko.com,布布扣    
bubuko.com,布布扣    private CoolInterface cool;
bubuko.com,布布扣
bubuko.com,布布扣    /* (non-Javadoc)
bubuko.com,布布扣     * @see junit.framework.TestCase#setUp()
bubuko.com,布布扣     */
bubuko.com,布布扣    protected void setUp() throws Exception
bubuko.com,布布扣    {
bubuko.com,布布扣        super.setUp();
bubuko.com,布布扣        
bubuko.com,布布扣        ctrl = MockControl.createControl(CoolInterface.class);
bubuko.com,布布扣        cool = (CoolInterface) ctrl.getMock();
bubuko.com,布布扣        
bubuko.com,布布扣        testInterface = new UseCoolInterface();
bubuko.com,布布扣        testInterface.setCoolInterface(cool);
bubuko.com,布布扣    }
bubuko.com,布布扣
bubuko.com,布布扣    /* (non-Javadoc)
bubuko.com,布布扣     * @see junit.framework.TestCase#tearDown()
bubuko.com,布布扣     */
bubuko.com,布布扣    protected void tearDown() throws Exception
bubuko.com,布布扣    {
bubuko.com,布布扣        super.tearDown();
bubuko.com,布布扣    }
bubuko.com,布布扣
bubuko.com,布布扣    /**
bubuko.com,布布扣     * Test method for {@link org.lhj.cool.mock.UseCoolInterface#reverseString(java.lang.String)}.
bubuko.com,布布扣     */
bubuko.com,布布扣    public void testReverseString()
bubuko.com,布布扣    {        
bubuko.com,布布扣        ctrl.expectAndThrow(cool.reverseString(null), new NullPointerException());        
bubuko.com,布布扣        ctrl.expectAndReturn(cool.reverseString(""), null);
bubuko.com,布布扣        ctrl.expectAndReturn(cool.reverseString("AAaa"), "aaAA");
bubuko.com,布布扣        ctrl.expectAndReturn(cool.reverseString("aaAA"), "AAaa");
bubuko.com,布布扣        ctrl.replay();
bubuko.com,布布扣        
bubuko.com,布布扣        try
bubuko.com,布布扣        {
bubuko.com,布布扣            testInterface.reverseString(null);
bubuko.com,布布扣            fail();
bubuko.com,布布扣        }
bubuko.com,布布扣        catch (NullPointerException e)
bubuko.com,布布扣        {
bubuko.com,布布扣            //donothing
bubuko.com,布布扣        }
bubuko.com,布布扣        assertNull(testInterface.reverseString(""));
bubuko.com,布布扣        assertEquals("aaAA", testInterface.reverseString("AAaa"));
bubuko.com,布布扣        assertEquals("AAaa", testInterface.reverseString("aaAA"));
bubuko.com,布布扣        
bubuko.com,布布扣        ctrl.verify();
bubuko.com,布布扣    }
bubuko.com,布布扣}
bubuko.com,布布扣

 

从上面可以看出使用easymock的步骤:

1、在setUp时创建MockControl,它是控制mock object行为的类,参数传入欲打桩的接口的class。

2、从mockControl中getmock,返回mock object转化为本类型对象。

3、创建欲测试类并将mock object传进去。

以上几步代码为:

 

bubuko.com,布布扣        ctrl = MockControl.createControl(CoolInterface.class);
bubuko.com,布布扣        cool = (CoolInterface) ctrl.getMock();
bubuko.com,布布扣        
bubuko.com,布布扣        testInterface = new UseCoolInterface();
bubuko.com,布布扣        testInterface.setCoolInterface(cool);
bubuko.com,布布扣

 

4、使用mockControl对mock object进行设置,这一步又称为训练,代码为

 

bubuko.com,布布扣        ctrl.expectAndThrow(cool.reverseString(null), new NullPointerException());        
bubuko.com,布布扣        ctrl.expectAndReturn(cool.reverseString(""), null);
bubuko.com,布布扣        ctrl.expectAndReturn(cool.reverseString("AAaa"), "aaAA");
bubuko.com,布布扣        ctrl.expectAndReturn(cool.reverseString("aaAA"), "AAaa");
bubuko.com,布布扣

第一行意思是告诉mockControl,mock object的reverseString方法会被调用,传入的参数是null,并会抛出异常;第二行意思是告诉mockControl,mock object的reverseString方法会被调用,传入的参数是"",并返回null;其他行类似。

5、训练完之后可以接受检查了,代码为:

 

bubuko.com,布布扣        ctrl.replay();
bubuko.com,布布扣

 

6、现在可以进行测试了,以下是测试代码:

bubuko.com,布布扣        try
bubuko.com,布布扣        {
bubuko.com,布布扣            testInterface.reverseString(null);
bubuko.com,布布扣            fail();
bubuko.com,布布扣        }
bubuko.com,布布扣        catch (NullPointerException e)
bubuko.com,布布扣        {
bubuko.com,布布扣            //donothing
bubuko.com,布布扣        }
bubuko.com,布布扣        assertNull(testInterface.reverseString(""));
bubuko.com,布布扣        assertEquals("aaAA", testInterface.reverseString("AAaa"));
bubuko.com,布布扣        assertEquals("AAaa", testInterface.reverseString("aaAA"));
bubuko.com,布布扣

可以看出,这跟一般的JUnit语句是一样的。

7、检验测试结果

 

bubuko.com,布布扣        ctrl.verify();
bubuko.com,布布扣

 

mockControl会验证mockObject是否按照训练的情况参与了测试,即训练时的方法是否被调用了,传入的参数对不对。

         以上示例只是easymock的一部分功能,除此之外,easymock还能测试mockObject的方法是否按照顺序调用了,调用的次数对不对,传入的参数是否在给定的范围之内,另外还可以改变参数对象的内容。

        除了easymock可以mock接口外,像mock objects,Jmock,mock Creator都可以实现此类功能。其中mock Creator还可以mock class,但是可惜mock creator是静态打桩的,实现起来有额外的工作。我在公司里用的是jdk1.4,无法用easymockclassextension1.2,所以使用了easymock加mock creator,幸好mock creator有eclipse插件,生成mock class也比较方便。所以如果你使用的是JDK1。4,用easymock加mock creator绝对是最佳组合;如果你使用的是JDK1.5,那么使用easymock加easymockclassextension会使你工作更轻松。

 
来自:http://blog.csdn.net/hardblackking/article/details/1544519

Java单元测试进阶之如何打桩(用easymock轻松打桩),布布扣,bubuko.com

Java单元测试进阶之如何打桩(用easymock轻松打桩)

标签:des   blog   http   java   使用   art   

原文地址:http://www.cnblogs.com/heidsoft/p/3832250.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!