如何在easymock中模拟一个返回其参数之一的方法?
Posted
技术标签:
【中文标题】如何在easymock中模拟一个返回其参数之一的方法?【英文标题】:How can I mock a method in easymock that shall return one of its parameters? 【发布时间】:2011-02-09 15:56:25 【问题描述】:public Object doSomething(Object o);
我想模拟。它应该只返回它的参数。我试过了:
Capture<Object> copyCaptcher = new Capture<Object>();
expect(mock.doSomething(capture(copyCaptcher)))
.andReturn(copyCatcher.getValue());
但没有成功,我只得到一个 AssertionError java.lang.AssertionError: Nothing captured yet
。有什么想法吗?
【问题讨论】:
【参考方案1】:嗯,最简单的方法是在 IAnswer 实现中使用 Capture...当内联执行此操作时,您当然必须声明它final
。
MyService mock = createMock(MyService.class);
final Capture<ParamAndReturnType> myCapture = new Capture<ParamAndReturnType>();
expect(mock.someMethod(capture(myCapture))).andAnswer(
new IAnswer<ParamAndReturnType>()
@Override
public ParamAndReturnType answer() throws Throwable
return myCapture.getValue();
);
replay(mock)
这可能是最准确的方式,无需依赖某些上下文信息。这每次都对我有用。
【讨论】:
我更喜欢 Remi Fouilloux 的帖子,并且经常使用它。它消除了对捕获对象的需要。 很好的答案。使用 Java 8 lambda 的整个 IAnswer 匿名子类可以重写为“myCapture::getValue”。【参考方案2】:我一直在寻找相同的行为,最后写了以下内容:
导入 org.easymock.EasyMock; 导入 org.easymock.IAnswer; /** * 使捕获的参数能够回答期望。 * 例如Factory接口定义如下 * * CharSequence 编码(最终的 CharSequence 数据); * * 出于测试目的,我们不需要实现此方法,因此应该对其进行模拟。 * * 最终工厂 factory = mocks.createMock("factory", Factory.class); * final ArgumentAnswer我在类的 javadoc 中写了一个快速的“操作方法”。
希望这会有所帮助。
【讨论】:
谢谢!尽管我更改了原始单元测试,但我相信我会再次遇到这个问题! (您可能想将其贡献给 EM 直接?) Capture 在您的 javadoc 示例中是一个红鲱鱼 - 它不是必需的:EasyMock.expect(factory.encode(anyObject())).andAnswer(parrot).anyTimes(); 不幸的是,版主已决定删除具有误导性和未使用的Capture
的编辑是“完全多余或严重损害可读性”,并且它不会“努力维护帖子所有者的目标"。【参考方案3】:
捕获用于测试之后传递给模拟的值。如果你只需要一个mock来返回一个参数(或从参数计算的一些值),你只需要实现IAnswer。
如果您想要一种可重用的方式将参数 X 传回,请参阅“Remi Fouilloux”的实现,但请忽略他在示例中对 Capture 的使用。
如果你只是想像“does_the_trick”的例子一样内联它,Capture 在这里是一个红鲱鱼。这是简化版:
MyService mock = createMock(MyService.class);
expect(mock.someMethod(anyObject(), anyObject()).andAnswer(
new IAnswer<ReturnType>()
@Override
public ReturnType answer() throws Throwable
// you could do work here to return something different if you needed.
return (ReturnType) EasyMock.getCurrentArguments()[0];
);
replay(mock)
【讨论】:
不完全是,我的意思是在“Remi Fouilloux”的代码中,不需要捕获 javadoc 示例。在“does_the_trick”的示例代码中也不需要它,如上所述。【参考方案4】:基于@does_the_trick 并使用 lambda,您现在可以编写以下代码:
MyService mock = EasyMock.createMock(MyService.class);
final Capture<ParamAndReturnType> myCapture = EasyMock.newCapture();
expect(mock.someMethod(capture(myCapture))).andAnswer(() -> myCapture.getValue());
或者像@thetoolman 建议的那样不捕获
expect(mock.someMethod(capture(myCapture)))
.andAnswer(() -> (ParamAndReturnType)EasyMock.getCurrentArguments()[0]);
【讨论】:
感谢 EasyMock.newCapture(),现在您似乎无法像其他示例一样使用 new 实例化 Capture;这是一个私有构造函数。【参考方案5】:嗯,如果我正确理解你的问题,我想你可能过于复杂了。
Object someObject = .... ;
expect(mock.doSomething(someObject)).andReturn(someObject);
应该可以正常工作。请记住,您同时提供了预期的参数和返回值。所以在两部作品中使用相同的对象。
【讨论】:
我不知道“someObject”。它以我要测试的方法实例化。想想一个方法“createImage(InputStream image)”(cut),它在内部调用了一个“Image filter(Image imge)”(mock)。 啊。好的。然后你可以做几件事。首先,您可以使用 isA() 参数匹配器测试该对象是一个特定的类。其次,我建议编写自己的论点捕获。我还没有这样做,但我已经编写了自己的参数匹配器。例如,如果您想检查 bean 属性,这非常有用。不幸的是我没有那个代码了,但是如果你看一下编写匹配器的例子,这并不难。 您的代码是有效的,但它没有回答使用参数之一的问题 - 它使用的是已知对象。以上是关于如何在easymock中模拟一个返回其参数之一的方法?的主要内容,如果未能解决你的问题,请参考以下文章