jMock用法简介 
总体上来说,jMock 是一个轻量级的模拟对象技术的实现。它具有以下特点: 
1.可以用简单易行的方法定义模拟对象,无需破坏本来的代码结构表; 
2.可以定义对象之间的交互,从而增强测试的稳定性; 
3.可以集成到测试框架; 
4.易扩充;
使用 jMock 模拟对象 
我们首先必须引入 jMock 的类,定义我们的测试类,创建一个 Mockery 的对象用来代表上下文。上下文可以模拟出对象和对象的输出,并且还可以检测应用是否合法。 
 
 @SuppressWarnings("unchecked")
@SuppressWarnings("unchecked")

 public class BookListTest
public class BookListTest  {
{

 private final Mockery context = new JUnit4Mockery()
    private final Mockery context = new JUnit4Mockery()  {
{

 
         {
{
 // 声明针对类进行mock,针对接口则会采用动态代理,不需要声明
            // 声明针对类进行mock,针对接口则会采用动态代理,不需要声明
 setImposteriser(ClassImposteriser.INSTANCE);
            setImposteriser(ClassImposteriser.INSTANCE);
 }
        }
 };
    };
 }
}


context 对象便可以用来创建Mock对象。
接下来的例子,我们模拟一个ServiceCall对象,我们以它的Map call(String target, Map dataMap)为例,针对此方法,设定预期值。然后我们在执行用例的时候调用此方法,便可以得到预期值。 
 @SuppressWarnings("unchecked")
@SuppressWarnings("unchecked")

 public class BookListTest
public class BookListTest  {
{

 private final Mockery context = new JUnit4Mockery()
    private final Mockery context = new JUnit4Mockery()  {
{

 
         {
{
 setImposteriser(ClassImposteriser.INSTANCE);
            setImposteriser(ClassImposteriser.INSTANCE);
 }
        }
 };
    };

 @Test
    @Test

 public void testExecuteNormal() throws Exception
    public void testExecuteNormal() throws Exception  {
{
 final ServiceCall sCall = context.mock(ServiceCall.class);
        final ServiceCall sCall = context.mock(ServiceCall.class);

 context.checking(new Expectations()
        context.checking(new Expectations()  {
{

 
             {
{
 one(sCall).call(JMockService.queryDtlInfo, null);
                one(sCall).call(JMockService.queryDtlInfo, null);
 // 构建预期结果
                // 构建预期结果
 Map ret = new HashMap();
                Map ret = new HashMap();
 ret.put("OrderId", "9800000000");
                ret.put("OrderId", "9800000000");
 ret.put("Data", new ArrayList());
                ret.put("Data", new ArrayList());
 // 设定预期值
                // 设定预期值
 will(returnValue(ret));
                will(returnValue(ret));
 
                
 // 第二次被调用时,返回null
                // 第二次被调用时,返回null
 one(sCall).call(JMockService.queryDtlInfo, new HashMap());
                one(sCall).call(JMockService.queryDtlInfo, new HashMap());
 will(returnValue(null));
                will(returnValue(null));
 }
            }
 });
        });

 BookList bListAction = new BookList();
        BookList bListAction = new BookList();
 bListAction.setName("jnbzwm");
        bListAction.setName("jnbzwm");
 // 设定ServiceCall对象为Mock对象
        // 设定ServiceCall对象为Mock对象
 bListAction.setServiceCall(sCall);
        bListAction.setServiceCall(sCall);

 // 执行Action方法
        // 执行Action方法
 bListAction.execute();
        bListAction.execute();

 Assert.assertEquals("9800000000", bListAction.getOrderId());
        Assert.assertEquals("9800000000", bListAction.getOrderId());
 Assert.assertEquals(0, bListAction.getDataList().size());
        Assert.assertEquals(0, bListAction.getDataList().size());
 }
    }


校验expectations中的规则 
使用jMock时,一般会通过如下代码指定expectations: 

 private final Mockery context = new JUnit4Mockery()
private final Mockery context = new JUnit4Mockery()  {
{

 
         {
{
 setImposteriser(ClassImposteriser.INSTANCE);
            setImposteriser(ClassImposteriser.INSTANCE);
 }
        }
 };
    };

 @Test
    @Test

 public void testExecuteNormal() throws Exception
    public void testExecuteNormal() throws Exception  {
{
 final ServiceCall sCall = context.mock(ServiceCall.class);
        final ServiceCall sCall = context.mock(ServiceCall.class);

 context.checking(new Expectations()
        context.checking(new Expectations()  {
{

 
             {
{
 one(sCall).call(JMockService.queryDtlInfo, null);
                one(sCall).call(JMockService.queryDtlInfo, null);
 // 构建预期结果
                // 构建预期结果
 Map ret = new HashMap();
                Map ret = new HashMap();
 ret.put("OrderId", "9800000000");
                ret.put("OrderId", "9800000000");
 ret.put("Data", new ArrayList());
                ret.put("Data", new ArrayList());
 // 设定预期值
                // 设定预期值
 will(returnValue(ret));
                will(returnValue(ret));
 
                
 // 第二次被调用时,返回null
                // 第二次被调用时,返回null
 one(sCall).call(JMockService.queryDtlInfo, new HashMap());
                one(sCall).call(JMockService.queryDtlInfo, new HashMap());
 will(returnValue(null));
                will(returnValue(null));
 }
            }
 });
        });
 
         .
.
 }
    }
 }
}

为了校验expectations中的规则是否都满足,可以在测试完成后通过增加 context.assertIsSatisfied()方法来验证expectations是否满足。
如下代码: 
 @Test
    @Test

 public void testExecuteNormal() throws Exception
    public void testExecuteNormal() throws Exception  {
{
 final ServiceCall sCall = context.mock(ServiceCall.class);
        final ServiceCall sCall = context.mock(ServiceCall.class);

 context.checking(new Expectations()
        context.checking(new Expectations()  {
{

 
             {
{
 one(sCall).call(JMockService.queryDtlInfo, null);
                one(sCall).call(JMockService.queryDtlInfo, null);
 // 构建预期结果
                // 构建预期结果
 Map ret = new HashMap();
                Map ret = new HashMap();
 ret.put("OrderId", "9800000000");
                ret.put("OrderId", "9800000000");
 ret.put("Data", new ArrayList());
                ret.put("Data", new ArrayList());
 // 设定预期值
                // 设定预期值
 will(returnValue(ret));
                will(returnValue(ret));
 
                
 // 第二次被调用时,返回null
                // 第二次被调用时,返回null
 one(sCall).call(JMockService.queryDtlInfo, new HashMap());
                one(sCall).call(JMockService.queryDtlInfo, new HashMap());
 will(returnValue(null));
                will(returnValue(null));
 }
            }
 });
        });

 BookList bListAction = new BookList();
        BookList bListAction = new BookList();
 bListAction.setName("jnbzwm");
        bListAction.setName("jnbzwm");
 // 设定ServiceCall对象为Mock对象
        // 设定ServiceCall对象为Mock对象
 bListAction.setUpfServiceCall(sCall);
        bListAction.setUpfServiceCall(sCall);

 // 执行Action方法
        // 执行Action方法
 bListAction.execute();
        bListAction.execute();

 Assert.assertEquals("9800000000", bListAction.getOrderId());
        Assert.assertEquals("9800000000", bListAction.getOrderId());
 Assert.assertEquals(0, bListAction.getDataList().size());
        Assert.assertEquals(0, bListAction.getDataList().size());
 context.assertIsSatisfied();
        context.assertIsSatisfied(); 
 }
    }

由于我定义了两条规则,而第二条并未调用,所以此用例不会通过。 
同一个方法连续调用时返回不同的值 
有两种方法,第一种就是直接通过多次调用 will(returnValue(X))来指定。如: 
 @Test
    @Test

 public void testExecuteNormal() throws Exception
    public void testExecuteNormal() throws Exception  {
{
 final ServiceCall sCall = context.mock(ServiceCall.class);
        final ServiceCall sCall = context.mock(ServiceCall.class);

 context.checking(new Expectations()
        context.checking(new Expectations()  {
{

 
             {
{
 one(sCall).call(JMockService.queryDtlInfo, null);
                one(sCall).call(JMockService.queryDtlInfo, null);
 will(returnValue(0));
                will(returnValue(0));

 // 第二次被调用时,返回1
                // 第二次被调用时,返回1
 one(sCall).call(JMockService.queryDtlInfo, null);
                one(sCall).call(JMockService.queryDtlInfo, null);
 will(returnValue(1));
                will(returnValue(1));

 // 第三次被调用时,返回2
                // 第三次被调用时,返回2
 one(sCall).call(JMockService.queryDtlInfo, null);
                one(sCall).call(JMockService.queryDtlInfo, null);
 will(returnValue(2));
                will(returnValue(2));
 }
            }
 });
        });
 
        
 }
    }

然而第一种方法会增加维护成本,且缺乏可控性。jMock提供了第二种方法,即通过onConsecutiveCalls的action来实现返回不同的返回值。如: 
 
 @Test
    @Test

 public void testExecuteNormal() throws Exception
    public void testExecuteNormal() throws Exception  {
{
 final ServiceCall sCall = context.mock(ServiceCall.class);
        final ServiceCall sCall = context.mock(ServiceCall.class);

 context.checking(new Expectations()
        context.checking(new Expectations()  {
{

 
             {
{
 atLeast(1).of (sCall).call(JMockService.queryDtlInfo, null);
                atLeast(1).of (sCall).call(JMockService.queryDtlInfo, null);
 will(onConsecutiveCalls( returnValue(0),  returnValue(1),  returnValue(2)));
                will(onConsecutiveCalls( returnValue(0),  returnValue(1),  returnValue(2))); 
 }
            }
 });
        });
 
        
 }
    }


指定mock的方法抛出异常 
在will方法中直接使用throwException的action。参考如下语法:
one(sCall).call(JMockService.queryDtlInfo, null);
// 设定预期值,抛出异常
will(throwException(new BusinessException("~", "name can't empty.")));
结合测试异常一起使用,代码如下: 
 @Test(expected=BusinessException.class)
    @Test(expected=BusinessException.class)

 public void testExecuteNormal() throws Exception
    public void testExecuteNormal() throws Exception  {
{
 final ServiceCall sCall = context.mock(ServiceCall.class);
        final ServiceCall sCall = context.mock(ServiceCall.class);

 context.checking(new Expectations()
        context.checking(new Expectations()  {
{

 
             {
{
 one(sCall).call(JMockService.queryDtlInfo, null);
                one(sCall).call(JMockService.queryDtlInfo, null);
 // 构建预期结果
                // 构建预期结果
 Map ret = new HashMap();
                Map ret = new HashMap();
 ret.put("OrderId", "9800000000");
                ret.put("OrderId", "9800000000");
 ret.put("Data", new ArrayList());
                ret.put("Data", new ArrayList());
 // 设定预期值
                // 设定预期值
 will(throwException(new BusinessException("~", "name can't empty.")));
                will(throwException(new BusinessException("~", "name can't empty.")));

 // 第二次被调用时,返回null
                // 第二次被调用时,返回null
 one(sCall).call(JMockService.queryDtlInfo, new HashMap());
                one(sCall).call(JMockService.queryDtlInfo, new HashMap());
 will(returnValue(null));
                will(returnValue(null));
 }
            }
 });
        });

 BookList bListAction = new BookList();
        BookList bListAction = new BookList();
 bListAction.setName("");
        bListAction.setName("");
 // 设定ServiceCall对象为Mock对象
        // 设定ServiceCall对象为Mock对象
 bListAction.setUpfServiceCall(sCall);
        bListAction.setUpfServiceCall(sCall);

 // 执行Action方法
        // 执行Action方法
 bListAction.execute();
        bListAction.execute();
 }
    }

