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

打桩(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版本。

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

先看欲打桩接口代码:

/************************************************************
 * Project Name: lhjTest
 * File Name   : CoolInterface.java
 * File Desc   : CoolInterface.java
 * Author      : Administrator
 * Create      : 2007-3-25
 * Modify:
 ***********************************************************/
package org.lhj.cool.junit;

/**
 * @author Administrator
 */
public interface CoolInterface
{
    String reverseString(String inputStr) throws NullPointerException;
}

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

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

/************************************************************
 * Project Name: lhjTest
 * File Name   : UseCoolInterface.java
 * File Desc   : UseCoolInterface.java
 * Author      : Administrator
 * Create      : 2007-3-25
 * Modify:
 ***********************************************************/
package org.lhj.cool.mock;

import org.lhj.cool.junit.CoolInterface;

/**
 * @author Administrator
 */
public class UseCoolInterface
{
    private CoolInterface cool;
    
    public void setCoolInterface(CoolInterface cool)
    {
        this.cool = cool;
    }
    
    public String reverseString(String inputStr) throws NullPointerException
    {
        return cool.reverseString(inputStr);
    }

}

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

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

/************************************************************
 * Project Name: lhjTest
 * File Name   : UseCoolInterfaceJTest.java
 * File Desc   : UseCoolInterfaceJTest.java
 * Author      : Administrator
 * Create      : 2007-3-25
 * Modify:
 ***********************************************************/
package org.lhj.cool.mock;

import junit.framework.TestCase;

import org.easymock.MockControl;
import org.lhj.cool.junit.CoolInterface;
import org.lhj.cool.mock.UseCoolInterface;

/**
 * @author Administrator
 */
public class UseCoolInterfaceJTest extends TestCase
{
    private UseCoolInterface testInterface;
    
    private MockControl ctrl;
    
    private CoolInterface cool;

    /* (non-Javadoc)
     * @see junit.framework.TestCase#setUp()
     */
    protected void setUp() throws Exception
    {
        super.setUp();
        
        ctrl = MockControl.createControl(CoolInterface.class);
        cool = (CoolInterface) ctrl.getMock();
        
        testInterface = new UseCoolInterface();
        testInterface.setCoolInterface(cool);
    }

    /* (non-Javadoc)
     * @see junit.framework.TestCase#tearDown()
     */
    protected void tearDown() throws Exception
    {
        super.tearDown();
    }

    /**
     * Test method for {@link org.lhj.cool.mock.UseCoolInterface#reverseString(java.lang.String)}.
     */
    public void testReverseString()
    {        
        ctrl.expectAndThrow(cool.reverseString(null), new NullPointerException());        
        ctrl.expectAndReturn(cool.reverseString(""), null);
        ctrl.expectAndReturn(cool.reverseString("AAaa"), "aaAA");
        ctrl.expectAndReturn(cool.reverseString("aaAA"), "AAaa");
        ctrl.replay();
        
        try
        {
            testInterface.reverseString(null);
            fail();
        }
        catch (NullPointerException e)
        {
            //donothing
        }
        assertNull(testInterface.reverseString(""));
        assertEquals("aaAA", testInterface.reverseString("AAaa"));
        assertEquals("AAaa", testInterface.reverseString("aaAA"));
        
        ctrl.verify();
    }
}

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

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

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

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

以上几步代码为:

        ctrl = MockControl.createControl(CoolInterface.class);
        cool = (CoolInterface) ctrl.getMock();
        
        testInterface = new UseCoolInterface();
        testInterface.setCoolInterface(cool);

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

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

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

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

        ctrl.replay();

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

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

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

7、检验测试结果

        ctrl.verify();

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轻松打桩)

时间: 2024-10-12 03:34:53

Java单元测试进阶之如何打桩(用easymock轻松打桩)的相关文章

Java单元测试(Junit+Mock+代码覆盖率)

原文见此处 单元测试是编写测试代码,用来检测特定的.明确的.细颗粒的功能.单元测试并不一定保证程序功能是正确的,更不保证整体业务是准备的. 单元测试不仅仅用来保证当前代码的正确性,更重要的是用来保证代码修复.改进或重构之后的正确性. 一般来说,单元测试任务包括 接口功能测试:用来保证接口功能的正确性. 局部数据结构测试(不常用):用来保证接口中的数据结构是正确的 比如变量有无初始值 变量是否溢出 边界条件测试 变量没有赋值(即为NULL) 变量是数值(或字符) 主要边界:最小值,最大值,无穷大(

Junit Java单元测试

Junit是一种java单元测试的工具,让我们的测试提高效率 入门篇 我们先来看一个测试加法add的例子 先创建一个AddOperation的类(我们要测试的类) package work; publicclass AddOperation { publicint add(int x,int y){ return x+y; } } 给该类添加测试类 详细请看图 选择你要测试的类 package work; importstatic org.junit.Assert.*; import org.j

有效使用Mock编写java单元测试

有效使用Mock编写java单元测试:http://blog.csdn.net/chjttony/article/details/14522771 单元测试mock框架--jmockit实战:http://blog.csdn.net/ultrani/article/details/8993364 使用 EasyMock 更轻松地进行测试:http://www.ibm.com/developerworks/cn/java/j-easymock.html 使用mock测试: http://blog.

Java单元测试框架 JUnit

Java单元测试框架 JUnit JUnit是一个Java语言的单元测试框架.它由Kent Beck和Erich Gamma建立,逐渐成为源于KentBeck的sUnit的xUnit家族中为最成功的一个. JUnit有它自己的JUnit扩展生态圈.多数Java的开发环境都已经集成了JUnit作为单元测试的工具. 在线Javadoc:http://ww...更多JUnit信息 最近更新: JUnit 4.12 发布,Java 单元测试框架 发布于4个月前 C++模拟测试框架 Google Mock

原!关于java 单元测试的一些总结

最近项目有在写java代码的单元测试,然后在思考一个问题,为什么要写单元测试??单元测试写了有什么用??百度了一圈,如下: 软件质量最简单.最有效的保证: 是目标代码最清晰.最有效的文档: 可以优化目标代码的设计: 是代码重构的保障: 是回归测试和持续集成的基石. 由于开发经验有限,可能说的不太对,但是是我目前的个人的观点,写单元测试,有时候确实可以发现bug,但是发现bug次数很少,而且目前都是项目开发完了,要上线了,公司有80%的覆盖率要求,所以都是后期上线之前补.目前而言,并没有在很认真地

Java单元测试(Junit+Mock+代码覆盖率)---------转

Java单元测试(Junit+Mock+代码覆盖率) 原文见此处 单元测试是编写测试代码,用来检测特定的.明确的.细颗粒的功能.单元测试并不一定保证程序功能是正确的,更不保证整体业务是准备的. 单元测试不仅仅用来保证当前代码的正确性,更重要的是用来保证代码修复.改进或重构之后的正确性. 一般来说,单元测试任务包括 接口功能测试:用来保证接口功能的正确性. 局部数据结构测试(不常用):用来保证接口中的数据结构是正确的 比如变量有无初始值 变量是否溢出 边界条件测试 变量没有赋值(即为NULL) 变

java web进阶篇(四) Tomcat数据源

动态web开发的最大特点是可以进行数据库的操作,传统的jdbc操作由于步骤重复性造成程序性能下降. 先来回顾JDBC的操作原理 1.加载数据库驱动程序,数据库驱动程序通过classpath配置. 2.通过DirverManager类取得数据库连接对象. 3.通过Connection实例化PreparedStatement对象,编写sql语句命令操作数据库. 4.数据库属于资源操作,操作完成后要关闭数据库以释放资源. 其实以上操作,1.2.4步骤是重复的,保留3,实际上就是数据源产生的原因. 数据

Java 单元测试Junit

@Test @Before @After 测试方法运行前执行Before动作(比如创建资源),运行后执行After动作(比如销毁资源) @BeforeClass @AfterClass 测试类运行前执行Before动作(比如创建资源),运行后执行After动作(比如销毁资源) Assert 对方法结果进行判断,是否等于希望值,是否为空等 表示测试通过不通过 Java 单元测试Junit,布布扣,bubuko.com

3.Java异常进阶

3.JAVA异常进阶 1.Run函数中抛出的异常 1.run函数不会抛出异常 2.run函数的异常会交给UncaughtExceptionhandler处理 3.默认的UncaughtExceptionHandler为空   Thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler(){-...}) 4.启动线程 Thread.start() 例子 UncaughtExceptionTask task=new Uncaught