EasyMock:无效方法

Posted

技术标签:

【中文标题】EasyMock:无效方法【英文标题】:EasyMock: Void Methods 【发布时间】:2010-10-25 22:24:26 【问题描述】:

我有一个方法在一个类中返回 void,该类是我要测试的类的依赖项。

这个类很大,我只使用其中的一个方法。 我需要为测试替换此方法的实现,因为我希望它做一些不同的事情,并且我需要能够访问此方法接收的参数。

我在EasyMock 中找不到这样做的方法。我想我知道如何使用Mockito 使用doAnswer 来做到这一点,但除非绝对必要,否则我不想添加另一个库。

【问题讨论】:

【参考方案1】:

如果我理解您想要正确执行的操作,您应该可以使用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 User Guide 解释:

创建返回值或异常

有时我们希望我们的模拟对象返回一个值或抛出一个在实际调用时创建的异常。从 EasyMock 2.2 开始,expectLastCall()expect(T value) 返回的对象提供了 andAnswer(IAnswer answer) 方法,它允许 [您] 指定用于创建返回值或异常的接口 IAnswer 的实现。

IAnswer 回调中,传递给模拟调用的参数可通过EasyMock.getCurrentArguments() 获得。如果你使用这些,像重新排序参数这样的重构可能会破坏你的测试。您已收到警告。

【讨论】:

【参考方案2】:

如果您只是在每次期望调用 void 方法时调用它,然后在调用 replay() 之前调用 EasyMock.expectLastCall(),Easymock 将“记住”每次调用。

所以我认为您不需要显式调用 expect()lastCall 除外),因为除了调用之外,您对 void 方法没有任何期望。

谢谢克里斯!

“Fun With EasyMock” 的 *** 用户 Burt Beckwith 是一篇很好的博文,提供了更多详细信息。值得注意的摘录:

基本上我倾向于使用的流程是:

    创建一个模拟 为每个预期的呼叫呼叫expect(mock.[method call]).andReturn([result]) 调用mock.[method call],然后为每个预期的无效调用调用EasyMock.expectLastCall() 拨打replay(mock)从“录制”模式切换到“回放”模式 根据需要注入模拟 调用测试方法 致电verify(mock) 以确保所有预期的呼叫都发生了

【讨论】:

我认为这个答案并没有解决这个问题——他不想仅仅断言对方法的期望,还想替换它的实现。 好点,马特,另一方面,这篇文章帮助我意识到为什么期望方法在这里并不适用。【参考方案3】:

如果您只想稍后访问参数,您可能还会喜欢 Captures 类,它是 EasyMock 2.4 的新功能。

您可以使用“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());

【讨论】:

【参考方案4】:

您可能想查看 PowerMock。 EasyMock 基于代理反射 API,这意味着一切都是代理,您只能测试接口,因此只能测试非最终方法和类。这可能对某些人有用,但如果您正在测试构建的世界,您将需要更多功能。

借助 PowerMock,Java 5 检测 API 消除了这些限制。无需编写要测试的对象的模拟对象实现(只是丑陋的 IMO)。将 PowerMock 与 Mockito(或 JMockit)结合使用,您将真正参加比赛。

当然,还有另一个方向是重写代码以便更容易测试,如果可能的话,这通常也是一个好主意。

【讨论】:

【参考方案5】:

在这种情况下,我发现在我的单元测试类中创建一个嵌套类并以这种方式覆盖具有特殊要求的方法是最好的方法。因此,如果您正在测试 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
    

在我的单元测试代码中,我只使用这个实例。只需将其视为任何其他模拟对象即可。比混合库容易得多,我同意这可能不是一个好主意。

【讨论】:

已经考虑过了。但它是一个抽象类,因此我需要提供大约 20 个空方法实现或子类其中一个子类,这对于查看测试的其他开发人员来说可能有点混乱。 哦,好吧。我不知道它是抽象的。如果您使用的是 IDE(我假设您使用的是 Eclipse 或 NetBeans),它可以为您提取所有这些抽象方法,您只需在它们上方添加注释来解释您在做什么。不是一个非常程序化的解决方案,但至少其他开发人员不会被它弄糊涂。

以上是关于EasyMock:无效方法的主要内容,如果未能解决你的问题,请参考以下文章

模拟无效方法的try catch块并使用EasyMock或Mockito捕获异常

EasyMock失败的测试用例“无效使用参数匹配器! 2匹配预期,1记录“错误

EasyMock 作废方法

带有 void 方法的 EasyMock 期望

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

easymock笔记2