PowerMockito:模拟私有方法抛出私有 class

PowerMockito: mock private method to throw private class

我有一个 class 看起来像这样:

public class Foo {
  public meth() {
    try {
      privMethod();
      System.out.println("Yay!");
    } catch (FooException e) {
      System.out.println("Boo!");
    }
  }

  private void privMethod() throws FooException {
    //doOtherStuff
    if (someCondition()) {
      throw new FooException();
    }
  }

  private class FooException extends Exception {
    FooException(String message) { super(message); }
  }
}

我想为此编写一个单元测试,使用 Mockito and Powermock。我知道我可以像这样模拟私有方法:

Foo spy = PowerMockito.spy(new Foo())
PowerMockito.doNothing().when(spy, "privMethod");

但是我该如何告诉它抛出异常呢?我知道它会是这样的:

Powermockito.doThrow(/*what goes here?*/).when(spy, "privMethod");

那里有什么?

请注意,异常是私有内部 class,所以我不能只做 doThrow(new FooException()),因为无法从单元测试访问 FooException

一般,你去。

Powermockito.doThrow(theThingToThrow)

去那里。例如 doThrow(new RuntimeException("should be thrown"))。或者更具体的异常,具体取决于您希望被测代码对异常执行的操作。

但当然:您想在那里实例化一个私有 class。这是您做不到的(很简单,请参阅 here 了解非常复杂的方法)。从这个角度来看:您创建了一个非常难以测试的设计。答案是重新设计该设计,使其更易于测试。

最后一句警告:我认为您不需要为此使用 PowerMockito。间谍使用普通的 Mockito。

并且当没有硬性需要使用PowerMock(ito) 版本时,则不要使用它们。时期。他们有自己的位置,但老实说:大多数情况下,需要 PowerMock(ito) 等于 "hard to test code"。

除此之外:查看私有方法转化为测试实现细节。这也是应尽可能避免的事情。

因此,换句话说:A) 几乎不可能以有意义的方式测试上述代码。 B)这样做也是不好的做法(如问题中所设想的那样)。因此 "best" 这里的解决方案是退后一步,重新设计整个事情。是的,我是认真的。