EasyMock:无效方法

时间:2009-05-13 16:39:13

标签: java unit-testing mocking void easymock

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

这个类很庞大,我只使用这个单一的方法。 我需要为测试替换此方法的实现,因为我希望它能够执行不同的操作,我需要能够访问此方法接收的参数。

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

5 个答案:

答案 0 :(得分:90)

如果我理解您要正确执行的操作,则应该可以使用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),允许[you]指定用于创建的IAnswer接口的实现。返回值或例外。

     

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

答案 1 :(得分:22)

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

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

谢谢Chris!

StackOverflow用户“Fun With EasyMock”

Burt Beckwith是一篇很好的博客文章,提供了更多详细信息。值得注意的摘录:

  

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

     
      
  1. 创建模拟
  2.   
  3. 为每个预期的来电致电expect(mock.[method call]).andReturn([result])
  4.   
  5. 为每个预期的无效通话
  6. 致电mock.[method call],然后致电EasyMock.expectLastCall()   
  7. 致电replay(mock)以从“记录”模式切换到“回放”模式
  8.   
  9. 根据需要注入模拟
  10.   
  11. 调用测试方法
  12.   
  13. 致电verify(mock)以确保所有预期电话都已发生
  14.   

答案 2 :(得分:5)

如果您只想稍后访问这些参数,您可能还会欣赏EasyMock 2.4中新增的Captures类。

您可以使用“Capture”类的实例代替匹配器。调用mocked方法时,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());

答案 3 :(得分:1)

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

使用PowerMock,Java 5 instrumentation API消除了限制。无需编写要测试的对象的模拟对象实现(只是丑陋的IMO)。将PowerMock与Mockito(或JMockit)结合在一起,你真的会参加比赛。

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

答案 4 :(得分:-1)

在这些情况下,我发现在单元测试类中创建嵌套类并以这种方式覆盖具有特殊要求的方法是最佳途径。因此,如果您使用您需要访问的参数测试具有该方法的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
    }
}

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