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

Java 我可以使用doReturn使用PowerMockito链接退货吗?,java,unit-testing,mockito,powermockito,Java,Unit Testing,Mockito,Powermockito,我有一个方法调用,第一次调用时需要返回valueA,第二次调用时需要返回valueB。我使用的是PowerMockito spy,因此如果我只需要返回一个值,它将如下所示: PowerMockito.doReturn(valueA).when(mockedObject, "methodName"); PowerMockito.when(mockedObject, "methodName").thenReturn(valueA).thenReturn(valueB); 看起来我可以像这样做链接

我有一个方法调用,第一次调用时需要返回valueA,第二次调用时需要返回valueB。我使用的是PowerMockito spy,因此如果我只需要返回一个值,它将如下所示:

PowerMockito.doReturn(valueA).when(mockedObject, "methodName");
PowerMockito.when(mockedObject, "methodName").thenReturn(valueA).thenReturn(valueB);
看起来我可以像这样做链接返回:

PowerMockito.doReturn(valueA).when(mockedObject, "methodName");
PowerMockito.when(mockedObject, "methodName").thenReturn(valueA).thenReturn(valueB);
但是我需要用doReturn指示链式返回,这样我的Spy就不会调用真正的methodName()

我已经试过了,但是Eclipse给了我一个错误,说它甚至无法编译:

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

甚至可以用doReturn和powermockito链接退货吗?如果是,怎么做?

我不这么认为。相反,您可以使用doAnswer和队列来实现它,如下所示

@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());
}
@测试
public void testReturnChain()引发异常{
示例示例=新示例(){
公共字符串getValue(){
返回null;
}
};
示例mockExample=spy(示例);
PowerMockito.doAnswer(新答案(){
私有最终队列值=新的LinkedList(Arrays.asList(“firstValue”、“secondValue”);
公共字符串应答(invocationMock invocationMock)抛出Throwable{
返回值。poll();
}
}).when(例如,“getValue”);
System.out.println(mockExample.getValue());
System.out.println(mockExample.getValue());
System.out.println(mockExample.getValue());
}
试试这个:

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

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

发生的事情是,
org.powermock.api.mockito.PowerMockito.doReturn
(等)将返回一个,它扩展了mockito的;在引擎盖下,延伸。因为PowerMock不需要更改功能,所以它不会覆盖这些调用;
PowerMockito.doReturn(foo).doReturn(bar)
中的第二个
doReturn
将调用Mockito的stuberImpl并返回Mockito stuber

这是一个问题,因为在转换到Stubber的过程中,当签名(如您需要的签名)时,您会丢失PowerMockito
。简言之,PowerMockito
doVerb
调用确实支持链接,并且确实支持以反射方式或按名称引用方法,但目前不能同时使用这两种方法


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

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

((PowerMockitoStubber) PowerMockito.doReturn(valueA).doReturn(valueB))
    .when(mockedObject, "methodName");
作为一个长期解决方案,因为任何返回PowerMockitoStuber的东西都必然返回Stuber,因此,对于所有PowerMockito用户来说,这可能完全可以通过接口覆盖来修复(请注意)。我没有对此进行测试,但可能很简单:

/* in PowerMockitoStubber.java, for each doVerb method: */
@Override public PowerMockitoStubber doNothing();
此时,您只需调整返回类型:

@Override public PowerMockitoStubber doNothing() {
  super.doNothing();
  return this;
}

由于PowerMock v1.6.5,您可以将多个值传递给

私有静态类示例{
公共字符串getValue(){
返回null;
}
}
@试验
public void testReturnChain()引发异常{
示例=新示例();
示例mockExample=PowerMockito.spy(示例);
doReturn(“firstValue”,“secondValue”).when(mockExample,“getValue”);
assertEquals(“firstValue”,mockExample.getValue());
assertEquals(“secondValue”,mockExample.getValue());
assertEquals(“secondValue”,mockExample.getValue());
}

其行为与:调用方法时定义连续返回值相同,最后一个返回值决定进一步调用的行为。

感谢您提供的详细答案,这非常有意义。我想知道为什么Eclipse允许我连续执行两个doReturn()调用,但随后将when()标记为无效。这肯定会成为一个很好的附加功能,我会考虑提出一个功能请求。谢谢你的帮助!我把它作为一个问题提交到这里,这对我来说是一个非常有用的补充!这成功了!我还没有在单元测试中使用答案,我甚至还没有真正研究它们。看到这一点后,我将不得不进行更多的调查