如何检查模拟方法的调用次数?

时间:2016-01-15 12:25:26

标签: java unit-testing mocking jmock

我有一个用@Before方法设置的模拟:

  @Before
  public void setup() {
    mockery.checking(new Expectations() {
      {
        allowing(mockExecutor).schedule(with(capture(runnableRef, Runnable.class)), with(0L), with(TimeUnit.MILLISECONDS));
      }
    });
  }

我已尝试为此测试用例添加一个特定的期望(仅在此处检查1):

mockery.checking(new Expectations() {
  {
    exactly(1).of(mockExecutor).schedule(with(capture(runnableRef, Runnable.class)), with(0L), with(TimeUnit.MILLISECONDS));
  }
});

然而,在结果中我可以看到它从未达到这个新的期望,因为它首先击中了“允许”:

java.lang.AssertionError: not all expectations were satisfied
expectations:
  allowed, already invoked 1 time: scheduledExecutorService.schedule(captured value <com.rbsfm.common.db.async.impl.ThrottledExecutor$1@eafc191>, <0L>, 
  expected once, never invoked: scheduledExecutorService.schedule(captured value <com.rbsfm.common.db.async.impl.ThrottledExecutor$1@eafc191>, <0L>, 

在大多数单元测试中,我并不关心调用schedule方法的频率(并且它在测试之间确实有所不同),但是在一个测试中,我希望检查它是否已被完全调用2次。

有没有办法做到这一点,而不必为每个测试用不同的数字重复模拟配置?

例如,我可以查询Mockery以了解该方法的调用频率吗?

1 个答案:

答案 0 :(得分:0)

这里讨论了这个场景:http://www.jmock.org/override.html(感谢Dick Hermann指出我的页面)。

基本思想是为测试设置状态机,并且只有在使用when状态机处于正确状态时才能使期望处于活动状态。

public class ChildTest extends TestCase {
    Mockery context = new Mockery();
    States test = context.states("test");

    Parent parent = context.mock(Parent.class);

    // This is created in setUp
    Child child;

    @Override
    public void setUp() {
        context.checking(new Expectations() {{
            ignoring (parent).addChild(child); when(test.isNot("fully-set-up"));
        }});

        // Creating the child adds it to the parent
        child = new Child(parent);

        test.become("fully-set-up");
    }

    public void testRemovesItselfFromOldParentWhenAssignedNewParent() {
        Parent newParent = context.mock(Parent.class, "newParent");

        context.checking(new Expectations() {{
            oneOf (parent).removeChild(child);
            oneOf (newParent).addChild(child);
        }});

        child.reparent(newParent);
    }
}