我可以使用doReturn链接PowerMockito的退货吗?

时间:2015-12-09 22:20:01

标签: java unit-testing mockito powermockito

我有一个方法调用,需要在第一次调用时返回valueA,并在第二次调用时返回valueB。我正在使用PowerMockito间谍,所以如果我只是需要返回一个值,它将如下所示:

PowerMockito.doReturn(valueA).when(mockedObject, "methodName");

看起来我可以像这样做链式回报:

PowerMockito.when(mockedObject, "methodName").thenReturn(valueA).thenReturn(valueB);

但我需要用doReturn指示链式返回,以便在我的间谍上不调用真正的methodName()。

我试过这个,但是Eclipse给了我一个错误,说它甚至都不会编译:

PowerMockito.doReturn(valueA).doReturn(valueB).when(mockedObject, "methodName");

甚至可以使用doReturn和powermockito链接回报吗?如果是这样,怎么样?

3 个答案:

答案 0 :(得分:1)

我不这么认为。相反,您可以使用下面的doAnswer和Queue来实现它

@Test
public void testReturnChain() throws Exception {
    Example example = new Example() {
        public String getValue() {
            return null;
        }
    };
    Example mockExample = spy(example);
    PowerMockito.doAnswer(new Answer<String>() {
        private final Queue<String> values = new LinkedList<String>(Arrays.asList("firstValue", "secondValue"));

        public String answer(InvocationOnMock invocationOnMock) throws Throwable {
            return values.poll();
        }
    }).when(mockExample, "getValue");

    System.out.println(mockExample.getValue());
    System.out.println(mockExample.getValue());
    System.out.println(mockExample.getValue());
}

答案 1 :(得分:1)

试试这个:

cchilders@main:~/projects$ pip freeze
Exception:
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/pip/basecommand.py", line 122, in main
    status = self.run(options, args)
  File "/usr/lib/python2.7/dist-packages/pip/commands/freeze.py", line 74, in run
    req = pip.FrozenRequirement.from_dist(dist, dependency_links, find_tags=find_tags)
  File "/usr/lib/python2.7/dist-packages/pip/__init__.py", line 299, in from_dist
    assert len(specs) == 1 and specs[0][0] == '=='
AssertionError

简而言之,我认为您在PowerMockito API中发现了一个漏洞。这可能是一个很好的事情,可以作为拉取请求提交,或者至少作为功能请求提交

发生了什么((PowerMockitoStubber) PowerMockito.doReturn(valueA).doReturn(valueB)) .when(mockedObject, "methodName"); (等人)将返回PowerMockitoStubber implementation,这扩展了Mockito的Stubber;在引擎盖下,PowerMockitoStubberImpl延伸StubberImpl。因为PowerMock不需要更改功能,所以它不会覆盖这些调用; org.powermock.api.mockito.PowerMockito.doReturn中的第二个doReturn将调用Mockito的StubberImpl并返回Mockito Stubber。

这是一个问题,因为在转换到Stubber时,您会丢失PowerMockito PowerMockito.doReturn(foo).doReturn(bar)签名,例如您需要的签名。 简而言之,PowerMockito when调用确实支持链接,并支持反射或按名称引用方法,但目前不是同时引用。

在内部,StubberImpl遵循构建器模式,在每次调用后返回:

doVerb

由于public Stubber doCallRealMethod() { answers.add(new CallsRealMethods()); return this; } 引用了this子类,因此很容易将Stubber转换为PowerMockitoStubber 以访问其他方法。对于上述解决方法,您自己制作演员:

PowerMockitoStubberImpl

作为长期解决方案,因为任何返回PowerMockitoStubber的内容都必须返回Stubber,因此可以仅通过界面覆盖(注意caveats listed on Joseph D. Darcy's Oracle Weblog)修复所有PowerMockito用户。我还没有对此进行测试,但这可能很容易:

((PowerMockitoStubber) PowerMockito.doReturn(valueA).doReturn(valueB))
    .when(mockedObject, "methodName");

此时您只需调整返回类型:

/* in PowerMockitoStubber.java, for each doVerb method: */
@Override public PowerMockitoStubber doNothing();

答案 2 :(得分:1)

从PowerMock v1.6.5开始,您可以将多个值传递给doReturn(Object toBeReturned, Object... othersToBeReturned)

malloc

行为与thenReturn(T value, T... values)相同:调用该方法时定义连续的返回值-最后一个确定后续调用的行为。