我可以使用 doReturn 将退货与 PowerMockito 链接在一起吗?



>我有一个方法调用,第一次调用时需要返回值A,第二次调用时需要返回值B。 我正在使用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联系起来吗? 如果是这样,如何?

从 PowerMock v1.6.5 开始,您可以将多个值传递给 doReturn(Object toBeReturn, Object...其他要返回(。

private static class Example {
    public String getValue() {
      return null;
    }
  }
  @Test
  public void testReturnChain() throws Exception {
    Example example = new Example();
    Example mockExample = PowerMockito.spy(example);
    PowerMockito.doReturn("firstValue", "secondValue").when(mockExample, "getValue");
    assertEquals("firstValue", mockExample.getValue());
    assertEquals("secondValue", mockExample.getValue());
    assertEquals("secondValue", mockExample.getValue());
  }

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

我不这么认为。相反,您可以使用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());
}

试试这个:

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

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

正在发生的事情是,org.powermock.api.mockito.PowerMockito.doReturn(等人(将返回一个PowerMockitoStubber实现,它扩展了Mockito的Stubber;在引擎盖下,PowerMockitoStubberImpl扩展了StubberImpl。由于 PowerMock 不需要更改功能,因此它不会重写这些调用;PowerMockito.doReturn(foo).doReturn(bar) 中的第二个doReturn将调用 Mockito 的 StubberImpl 并返回一个 Mockito Stubber。

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


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

public Stubber doCallRealMethod() {
    answers.add(new CallsRealMethods());
    return this;
}

由于this引用PowerMockitoStubberImpl子类,因此很容易将 Stubber 强制转换为 PowerMockitoStubber 以访问其他方法。对于上述解决方法,您自己制作强制转换:

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

作为一个长期的解决方案,因为任何返回PowerMockitoStubber的东西都必须返回Stubber,所以可以纯粹通过接口覆盖为所有PowerMockito用户修复这个问题(注意Joseph D. Darcy的Oracle博客上列出的警告(。我还没有测试过这个,但它可能很容易:

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

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

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

相关内容

  • 没有找到相关文章

最新更新