如何在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 parrot = new ArgumentAnswer(); * EasyMock.expect(factory.encode(EasyMock.capture(new Capture()))).andAnswer(parrot).anyTimes(); * * 创建于 2010 年 6 月 22 日。 * @作者雷米·弗卢克斯 * */ 公共类 ArgumentAnswer 实现 IAnswer 私有最终 int 参数偏移; 公共 ArgumentAnswer() 这(0); 公共 ArgumentAnswer(int offset) this.argumentOffset = 偏移量; /** * @inheritDoc */ @SuppressWarnings("未选中") public T answer() 抛出 Throwable final Object[] args = EasyMock.getCurrentArguments(); if (args.length

我在类的 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中模拟一个返回其参数之一的方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何 EasyMock 对返回通配符泛型的方法的调用?

EasyMock 为预期方法返回 Null

Easymock:如何在不可见的情况下模拟受保护方法的调用

java EasyMock对于有参无返回至的方法怎么模拟?

让 EasyMock 模拟对象抛出异常

如何使用 JUnit、EasyMock 或 PowerMock 模拟静态最终变量