带有 void 方法的 EasyMock 期望

Posted

技术标签:

【中文标题】带有 void 方法的 EasyMock 期望【英文标题】:EasyMock expectations with void methods 【发布时间】:2012-12-04 17:38:19 【问题描述】:

我正在使用 EasyMock 进行一些单元测试,但我不明白 EasyMock.expectLastCall() 的用法。正如您在下面的代码中看到的那样,我有一个对象,该对象的方法返回 void 在其他对象的方法中被调用。我认为我必须让 EasyMock 期望该方法调用,但我尝试注释掉 expectLastCall() 调用,它仍然有效。是因为我通过EasyMock.anyObject()) 将其注册为预期呼叫还是发生了其他事情?

MyObject obj = EasyMock.createMock(MyObject.class);
MySomething something = EasyMock.createMock(MySomething.class);
EasyMock.expect(obj.methodThatReturnsSomething()).andReturn(something);

obj.methodThatReturnsVoid(EasyMock.<String>anyObject());

// whether I comment this out or not, it works
EasyMock.expectLastCall();

EasyMock.replay(obj);

// This method calls the obj.methodThatReturnsVoid()
someOtherObject.method(obj);

EasyMock 的 API 文档这样说 expectLastCall()

Returns the expectation setter for the last expected invocation in the current thread. This method is used for expected invocations on void methods.

【问题讨论】:

这个问题不是我想要的,但它结合了 Yogendra 的答案和 cmets 帮助我理解了我的问题。感谢您先到这里。 【参考方案1】:

该方法通过IExpectationSetters返回给你期望的句柄;这使您能够验证(断言)您的 void 方法是否被调用以及相关行为,例如

EasyMock.expectLastCall().once();
EasyMock.expectLastCall().atLeastOnce();
EasyMock.expectLastCall().anyTimes();

IExpectationSetters 的详细 API 为 here

在您的示例中,您只是获取句柄,而没有对其进行任何操作因此您看不到拥有或删除该语句的任何影响。这与您调用某些 getter 方法或声明一些变量,不要使用它。

【讨论】:

我必须做什么(或我在做什么)使我的测试期望调用methodThatReturnsVoid()?只是在replay() 之前调用它? @SotiriosDelimanolis 正如我所提到的,使用EasyMock.expectLastCall().atLeastOnce(); 断言您的方法至少被成功调用了一次。 我明白了。但是如果我没有expectLastCall(),测试仍然通过。由于您没有让模拟对象期望它,它不应该失败吗? @SotiriosDelimanolis 测试将通过,因为这是断言语句而不是执行语句。希望您了解其中的区别。您编写的测试用例以验证代码的某些行为。这取决于您要验证的所有内容以及您需要相应地放置断言。 呃...EasyMock 是一个好的开始,但 Mockito 或 JMockit 跳过了这些环节。【参考方案2】:

当您需要进一步验证“该方法已被调用。(与设置期望相同)”以外的任何内容时,您只需要EasyMock.expectLastCall();

假设您想验证该方法被调用了多少次,因此您将添加以下任何一个:

EasyMock.expectLastCall().once();
EasyMock.expectLastCall().atLeastOnce();
EasyMock.expectLastCall().anyTimes();

或者说你要抛出异常

EasyMock.expectLastCall().andThrow()

如果您不在乎,那么EasyMock.expectLastCall(); 不是必需的,也没有任何区别,您的声明"obj.methodThatReturnsVoid(EasyMock.&lt;String&gt;anyObject());" 足以建立期望。

【讨论】:

【参考方案3】:

你缺少 EasyMock.verify(..)

MyObject obj = EasyMock.createMock(MyObject.class);
MySomething something = EasyMock.createMock(MySomething.class);
EasyMock.expect(obj.methodThatReturnsSomething()).andReturn(something);

obj.methodThatReturnsVoid(EasyMock.<String>anyObject());

// whether I comment this out or not, it works
EasyMock.expectLastCall();

EasyMock.replay(obj);

// This method calls the obj.methodThatReturnsVoid()
someOtherObject.method(obj);

// verify that your method was called
EasyMock.verify(obj);

【讨论】:

不,verify 是隐含的。这个问题在Yogendra's answer 中有解释。我没有正确地写出我的模拟期望。

以上是关于带有 void 方法的 EasyMock 期望的主要内容,如果未能解决你的问题,请参考以下文章

测试没有使用 EasyMock 调用 void 方法

期望任何东西作为参数来模拟使用 EasyMock

如何使用 EasyMock 测试 void 方法

EasyMock:无效方法

EasyMock andReturn() 与 andStubReturn()

如何在Java Unit Test中mock 静态方法