Java EasyMock:空方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/859031/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:17:51  来源:igfitidea点击:

EasyMock: Void Methods

javaunit-testingmockingvoideasymock

提问by Iker Jimenez

I have a method that returns void in a class that is a dependency of the class I want to test.

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

This class is huge and I'm only using this single method from it. I need to replace the implementation of this method for the test as I want it to do something different and I need to be able to access the parameters this method receives.

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

I cannot find a way of doing this in EasyMock. I think I know how to do it with Mockitoby using doAnswerbut I don't want to add another library unless absolutely necessary.

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

采纳答案by matt b

If I understand what you want to do correctly, you should be able to use andAnswer():

如果我理解您想要正确执行的操作,您应该能够使用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;
    }
});

The EasyMock User Guideexplains:

EasyMock的用户指南解释说:

Creating Return Values or Exceptions

Sometimes we would like our mock object to return a value or throw an exception that is created at the time of the actual call. Since EasyMock 2.2, the object returned by expectLastCall()and expect(T value)provides the method andAnswer(IAnswer answer)which allows [you] to specify an implementation of the interface IAnswerthat is used to create the return value or exception.

Inside an IAnswercallback, the arguments passed to the mock call are available via EasyMock.getCurrentArguments(). If you use these, refactorings like reordering parameters may break your tests. You have been warned.

创建返回值或异常

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

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

回答by Marc W

In situations like these I've found that making a nested class in my unit test class and overriding the methods with special requirements in that way is the best route. So if you're testing ClassAwhich has that method with the parameters you need to access, you'd do something like:

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

In my unit testing code, I then just use this instance instead. Just treat it as if it was any other mock object. Much easier than mixing libraries, which I agree is probably not a good idea.

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

回答by Edward Q. Bridges

If you just call the void method for each time you're expecting it to be invoked and then invoke EasyMock.expectLastCall()prior to calling replay(), Easymock will “remember” each invocation.

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

So I don't think you need to explicitly call expect()(other than lastCall) since you're not expecting anything from a void method, except its invocation.

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

Thanks Chris!

谢谢克里斯!

“Fun With EasyMock”by fellow StackOverflow user Burt Beckwithis a good blog post that provides more detail. Notable excerpt:

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

Basically the flow that I tend to use is:

  1. Create a mock
  2. call expect(mock.[method call]).andReturn([result])for each expected call
  3. call mock.[method call], then EasyMock.expectLastCall()for each expected void call
  4. call replay(mock)to switch from “record” mode to “playback” mode
  5. inject the mock as needed
  6. call the test method
  7. call verify(mock)to assure that all expected calls happened

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

  1. 创建一个模拟
  2. 呼叫expect(mock.[method call]).andReturn([result])每个预期的呼叫
  3. call mock.[method call],然后EasyMock.expectLastCall()对于每个预期的无效调用
  4. 调用replay(mock)从“记录”模式切换到“回放”模式
  5. 根据需要注入模拟
  6. 调用测试方法
  7. 调用verify(mock)以确保所有预期的调用都发生了

回答by piepera

If you only want access to the parameters for later, you might also appreciate the Capturesclass which is new to EasyMock 2.4.

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

You can use an instance of the "Capture" class in place of a matcher. When your mocked method is invoked, the Capture instance will store the parameter it was invoked with.

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

回答by Joseph Lust

You might want to check out PowerMock. EasyMock is based on the proxy reflection API meaning everything is a proxy and you can only test interfaces, and thus only non-final methods and classes. This might work for some, but if you're testing the world as built, you'll need more power.

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

With PowerMock the Java 5 instrumentation API removes the limitations. No need to write mock object implementations of the object to be tested (just ugly IMO). Couple PowerMock with Mockito (or JMockit) and you'll really be off to the races.

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

Of course, there is the other direction of rewriting your code to be more easily tested, which is generally a good idea too, if possible.

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