我有一个方法,该方法在要测试的类的依赖项的类中返回void。
此类非常庞大,我仅使用其中的一种方法。我需要替换该方法的实现以进行测试,因为我希望它做一些不同的事情,并且需要能够访问该方法接收的参数。
我在EasyMock中找不到做到这一点的方法。我想我知道如何使用Mockito做到这一点,doAnswer
但是除非绝对必要,否则我不想添加其他库。
Answers:
如果我了解您要正确执行的操作,则应该可以使用andAnswer()
:
mockObject.someMethod(eq(param1), eq(param2));
expectLastCall().andAnswer(new IAnswer() {
public Object answer() {
//supply your mock implementation here...
SomeClass arg1 = (SomeClass) getCurrentArguments()[0];
AnotherClass arg2 = (AnotherClass) getCurrentArguments()[1];
arg1.doSomething(blah);
//return the value to be returned by the method (null for void)
return null;
}
});
《EasyMock用户指南》解释了:
创建返回值或异常
有时我们希望我们的模拟对象返回一个值或引发在实际调用时创建的异常。从EasyMock 2.2开始,由
expectLastCall()
和返回的对象expect(T value)
提供了andAnswer(IAnswer answer)
[允许]指定IAnswer
用于创建返回值或异常的接口的实现的方法。在
IAnswer
回调内部,可以通过传递给模拟调用的参数EasyMock.getCurrentArguments()
。如果使用这些,则诸如重新排序参数之类的重构可能会破坏测试。你被警告了。
如果您只是希望在每次调用void方法时都调用它,然后在调用EasyMock.expectLastCall()
之前调用它replay()
,则Easymock将“记住”每次调用。
因此,我认为您不需要显式调用expect()
(除外lastCall
),因为您不会期望void方法(调用除外)中的任何内容。
谢谢克里斯!
StackOverflow的其他用户Burt Beckwith的“ Fun With EasyMock”是一篇不错的博客文章,提供了更多详细信息。摘录:
基本上,我倾向于使用的流程是:
- 创建一个模拟
- 呼叫
expect(mock.[method call]).andReturn([result])
每个预期的呼叫- 打电话
mock.[method call]
,然后EasyMock.expectLastCall()
对每项预期无效呼叫- 呼叫
replay(mock)
从“录制”模式切换到“播放”模式- 根据需要注入模拟
- 调用测试方法
- 呼叫
verify(mock)
以确保所有预期的呼叫均已发生
如果您只想稍后访问参数,您可能还会喜欢EasyMock 2.4新增的Captures类。
您可以使用“ Capture”类的实例代替匹配器。调用模拟方法时,Capture实例将存储使用其调用的参数。
Capture<ChartPanel> captured = new Capture<ChartPanel>();
// setChartPanel is going to be called during execution;
// we want to verify some things about the ChartPanel
// instance it's invoked with
chartMock.setChartPanel(capture(captured));
replay(chartMock);
ufdm.setChartAnnotater(chartMock);
// afterPropertiesSet triggers the setChartPanel call...
ufdm.afterPropertiesSet();
verify(chartMock);
// verify some things about the ChartPanel parameter our
// mock object was invoked with
assertSame(plot, captured.getValue().getChart().getPlot());
在这样的情况下,我发现在单元测试类中嵌套一个类并以这种方式覆盖具有特殊要求的方法是最好的方法。因此,如果您正在测试ClassA
哪种方法带有需要访问的参数,则可以执行以下操作:
class MockClassA extends ClassA {
@Override
void specialMethod(String param1, String param2) {
// do logging or manipulation of some sort
super.specialMethod(param1,param2); // if you need to
}
}
然后在我的单元测试代码中,我只是使用该实例。就像对待其他模拟对象一样对待它。比混合库要容易得多,我同意这可能不是一个好主意。