JMockit实践--(3)Expectations

声明:

Author:赵志乾

Date:2017-8-6

Declaration:All Right Reserved!!!



    1、在给定的测试中,一个expectation代表对一个特定的、被mocked的方法/构造函数的一组调用。它可能会涵盖测试过程中该方法的多个不同的调用,但这并非强制要求。而方法的一次调用是否匹配特定的expectation,不仅取决于方法签名,还包括传入参数、以及运行时已经匹配的调用次数。我们可以通过指定特定的参数值,使得特定的函数调用匹配特定的expectation。当然,也可以通过指定比较宽泛的匹配条件,使得同一方法的一组调用均能匹配该expectation。下面给出一个示例:

@Test
public void doBusinessOperationXyz(@Mocked final Dependency mockInstance)
{
   ...
   new Expectations() {{
      ...
      // An expectation for an instance method:
      mockInstance.someMethod(1, "test"); result = "mocked";
      ...
   }};

   // A call to code under test occurs here, leading to mock invocations
   // that may or may not match specified expectations.
}

    该示例给出的是Dependency#someMethod(int, String)方法的expectation,并且需要通过特定的参数匹配方法调用。

2、录制、重放、验证三阶段

    测试过程通常可以划分出三个顺序执行的阶段,如下例所示:

@Test
public void someTestMethod()
{
   // 1. Preparation: whatever is required before the code under test can be exercised.
   ...
   // 2. The code under test is exercised, usually by calling a public method.
   ...
   // 3. Verification: whatever needs to be checked to make sure the code exercised by
   //    the test did its job.
   ...
}

    首先是准备阶段,在该阶段主要是创建/获取测试过程中需要的对象和数据项。之后是在测试条件下执行代码。最后是结果的验证,即将执行结果和预期结果进行对比。而在基于行为测试(即包含mocked类型)的上下文中,我们通常会将测试过程划分为下面的三个阶段。

    首先是录制阶段,其主要是在mocked方法被调之前对其调用行为进行录制,即完成测试的准备工作。其次是重放阶段,该阶段是指代码执行过程中,如果mocked的方法被调用,将会重放前一阶段录制的行为,即mocked方法表现出预期的行为。最后是验证阶段,该阶段是在测试验证过程中发生,主要是验证mocked方法的调用和我们预期的是否一致。下面给出了使用JMockit的基于行为的测试模板:

import mockit.*;
... other imports ...

public class SomeTest
{
   // Zero or more "mock fields" common to all test methods in the class:
   @Mocked Collaborator mockCollaborator;
   @Mocked AnotherDependency anotherDependency;
   ...

   @Test
   public void testWithRecordAndReplayOnly(mock parameters)
   {
      // Preparation code not specific to JMockit, if any.

      new Expectations() {{ // an "expectation block"
         // One or more invocations to mocked types, causing expectations to be recorded.
         // Invocations to non-mocked types are also allowed anywhere inside this block
         // (though not recommended).
      }};

      // Unit under test is exercised.

      // Verification code (JUnit/TestNG assertions), if any.
   }

   @Test
   public void testWithReplayAndVerifyOnly(mock parameters)
   {
      // Preparation code not specific to JMockit, if any.

      // Unit under test is exercised.

      new Verifications() {{ // a "verification block"
         // One or more invocations to mocked types, causing expectations to be verified.
         // Invocations to non-mocked types are also allowed anywhere inside this block
         // (though not recommended).
      }};

      // Additional verification code, if any, either here or before the verification block.
   }

   @Test
   public void testWithBothRecordAndVerify(mock parameters)
   {
      // Preparation code not specific to JMockit, if any.

      new Expectations() {{
         // One or more invocations to mocked types, causing expectations to be recorded.
      }};

      // Unit under test is exercised.

      new VerificationsInOrder() {{ // an ordered verification block
         // One or more invocations to mocked types, causing expectations to be verified
         // in the specified order.
      }};

      // Additional verification code, if any, either here or before the verification block.
   }
}

    注意:一个测试可以包含任意数量的expectation块,甚至可以不包含。

    事实上,匿名内部类可以定界代码块,这可以让我们充分利用IDE中代码折叠的特性,如下面的这张图片所示:



注:本博客中的实例代码均来自于JMockit官方教程。




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫白小猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值