Java 使用 PowerMockito.whenNew() 不会被嘲笑并调用原始方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25317804/
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 00:05:22  来源:igfitidea点击:

Using PowerMockito.whenNew() is not getting mocked and original method is called

javajunitmockitopowermock

提问by user3942446

I have a code somewhat like this below:

我有一个类似于下面的代码:

Class A {
  public boolean myMethod(someargs) {
    MyQueryClass query = new MyQueryClass();
    Long id = query.getNextId();
    // some more code
  }
}
Class MyQueryClass     {
  ....
  public Long getNextId() {
    //lot of DB code, execute some DB query
    return id;
  }
}

Now I'am writing a test for A.myMethod(someargs). I want to skip the real method query.getNextId()and instead return a stub value. Basically, I want to mock MyQueryClass.

现在我正在为A.myMethod(someargs). 我想跳过真正的方法query.getNextId(),而是返回一个存根值。基本上,我想模拟MyQueryClass.

So in my test case, I have used:

所以在我的测试用例中,我使用了:

MyQueryClass query = PowerMockito.mock(MyQueryClass.class);
PowerMockito.whenNew(MyQueryClass.class).withNoArguments().thenReturn(query);
when(query.getNextId()).thenReturn(1000000L);

boolean b = A.getInstance().myMethod(args);

//asserts

I used @RunWith(PowerMockRunner.class)and @PrepareForTest({MyQueryClass.class})in the beginning of my test class.

我在测试课开始时使用了@RunWith(PowerMockRunner.class)@PrepareForTest({MyQueryClass.class})

But when I debug the test, it is still calling the real method getNextId()of the MyQueryClassclass.

但是我调试测试的时候,还是调用getNextId()MyQueryClass类的真正方法。

What am I missing here? Can anyone help as I am new to Mockito and PowerMockito.

我在这里缺少什么?任何人都可以提供帮助,因为我是 Mockito 和 PowerMockito 的新手。

采纳答案by TrueDub

You need to put the class where the constructor is calledinto the @PrepareForTestannotation instead of the class which is being constructed - see Mock construction of new objects.

您需要将调用构造函数@PrepareForTest的类而不是正在构造的类放入注释中 - 请参阅新对象的模拟构造

In your case:

在你的情况下:

? @PrepareForTest(MyQueryClass.class)

? @PrepareForTest(MyQueryClass.class)

? @PrepareForTest(A.class)

? @PrepareForTest(A.class)

More general:

更一般:

? @PrepareForTest(NewInstanceClass.class)

? @PrepareForTest(NewInstanceClass.class)

? @PrepareForTest(ClassThatCreatesTheNewInstance.class)

? @PrepareForTest(ClassThatCreatesTheNewInstance.class)

回答by ACV

As @TrueDub mentioned in his accepted reply, you need to add the class where the constructor is called to the @PrepareForTest.

正如@TrueDub 在他接受的答复中提到的,您需要将调用构造函数的类添加到@PrepareForTest.

However, if you do this, coverage for that class as reported by eclemma and Sonar will be zero for that class

但是,如果您这样做,则 eclemma 和 Sonar 报告的该类的覆盖率对于该类将为零

Powermockito wiki

Powermockito 维基

We are going to replace Javassist with ByteBuddy (#727) and it should help to resolve this old issue. But right now there is NO WAY TO USE PowerMock with JaCoCo On-the-fly instrumentation. And no workaround to get code coverage in IDE.

我们将用 ByteBuddy (#727) 替换 Javassist,它应该有助于解决这个老问题。但是现在没有办法将 PowerMock 与 JaCoCo On-the-fly 仪器一起使用。并且没有解决方法可以在 IDE 中获得代码覆盖率。

So the solution here would be to refactor the actual code to use a static factory that would return an instance of that class and then statically mock it.

因此,这里的解决方案是重构实际代码以使用静态工厂,该工厂将返回该类的实例,然后静态模拟它。

回答by jiajianchen

Perhaps you can simply use

也许你可以简单地使用

Mockito.doReturn(value).when(xxx)