Jmockit示例三部曲之三按我自己的思路走

好了,来到最后一个API,个人认为是十分十分有意思的API,叫做Jmockit Mockups API,前面说到过,这是一个state-oriented mocking API,这几天写了前两章后,有点小感悟,state是状态的意思,Expectations API和Verifications API,都是可以很灵活的匹配我们传入的参数,以得到之前录制的结果,而Mockups API可以完成的工作是,使用它,我们可以不关心是谁用它,就像前奏时说的,我们可以复写调用的依赖,根据不同的参数,设置返回不同的返回值,也就是不同的状态进行改变,这也是他有意思的地方。看看例子,会更容易明白。

package jmockit.tutorial.domain;

import java.util.*;
import org.apache.commons.mail.*;
import jmockit.tutorial.persistence.*;

import static org.junit.Assert.*;
import org.junit.*;
import mockit.*;

public final class MyBusinessService_MockupsAPI_Test
{
   public static final class MockDatabase extends MockUp<Database>
   {
      @Mock
      public void $clinit() { /* do nothing */ }

      @Mock(invocations = 1)
(1)   public List<EntityX> find(String ql, Object... args)
      {
         assertNotNull(ql);
         assertTrue(args.length > 0);
         return Arrays.asList(new EntityX(1, "AX5", "someone@somewhere.com"));
      }
   
      @Mock(maxInvocations = 1)
(2)   public void persist(Object o) { assertNotNull(o); }
   }

   @BeforeClass
   public static void mockUpPersistenceFacade()
   {
      // Applies the mock class by invoking its constructor:
      new MockDatabase();
   }

   final EntityX data = new EntityX(5, "abc", "5453-1");

   @Test
   public void doBusinessOperationXyz() throws Exception
   {
      // Defines and applies a mock class in one operation:
      new MockUp<Email>() {
         @Mock(invocations = 1)
         Email addTo(Invocation inv, String email)
         {
            assertEquals(data.getCustomerEmail(), email);
            return inv.getInvokedInstance();
         }

         @Mock(invocations = 1)
(4)      String send() { return ""; }
      };
   
      new MyBusinessService().doBusinessOperationXyz(data);
   }

   @Test(expected = EmailException.class)
   public void doBusinessOperationXyzWithInvalidEmailAddress() throws Exception
   {
      new MockUp<Email>() {
         @Mock
(3)      Email addTo(String email) throws EmailException
         {
            assertNotNull(email);
            throw new EmailException();
         }
         @Mock(invocations = 0)
         String send() { return null; }
      };
      new MyBusinessService().doBusinessOperationXyz(data);
   }
}
天哪,不用仔细看例子,都发现了内容比前两章多了不止一点点。这同样这第三个API有趣的地方,来仔细看看。
在这里,我们通过修改了感兴趣(其实也就是我们被测类的依赖)的类的方法,而不是使用通过record expectations或者verify expectation mock了的方法。注意,这里使用的词语,是修改,这就好像,我们调用的是自己复写的代码,而不是原来的产品代码,太神奇了,是不是。必须说明的是,这些修改的方法必须和真是的方法必须使用相同的signature,并且添加上@Mock,而如果含有static block的话,还必须使用像例子中的“$clinit”,否则就会出错,这个在后面会有介绍。

  @Mock
      public void $clinit() { /* do nothing */ }


这些需要mock的依赖可以定义在一个独立的类里面,像MockDatabase,或者定义在一个测试方法里面的匿名内部类,两个测试方面里面都有。不管是哪一种,都必须继承MockUp<T>这个基础类,并且将T替换为需要mock的类型(这个类型可是interface等等)。

示例中的两个test cases都重复的使用了一个mock class——MockDatabase,在一个@BeforeClass方法中执行了,这样在整个测试类的生命周期中都会起作用(记住,这个是必须的,因为需要创建这个instance,之后的测试方法中才能使用到它,否则将调用真实的产品代码了)。我们通过“$clinit()”stub out了static block的初始化,这是必须的,因为在static block的初始化中,需要创建一个EntityManagerFactory。

在每个test case里面都会通过内部匿名类创建一个被mock掉的Email类,在@Mock中可以看到有一些属性,像invocations,maxInvocations等,就像是Expectations API中的times和maxTimes一个意思,虽然在示例中没有提到,但是constructors可以通过"$init"进行mock,并且参数必须是匹配的。

很显然,我们的大部分的工作可以使用Expectations API或者Verifications API来完成,但是毫无疑问,有时我们使用Mockups API也会很有乐趣(或者是某种情况下,使用Mockups API会更好使),因为这就好比做我们自己复写了所有的依赖,并且自己可以随意设定传入的参数以及对应的返回结果。这才像真正的剥离依赖~

好了,官方的示例代码就介绍到这了,下面将逐节的介绍他们的使用方式和使用特点,以应对我们各种需要。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值