Java 如何使用PowerMockito模拟void方法?

Java 如何使用PowerMockito模拟void方法?,java,android,unit-testing,powermockito,spy,Java,Android,Unit Testing,Powermockito,Spy,这是一个复制品。也有很多类似的问题/答案,但没有一个对我有帮助。由于有数百名开发人员接受了一些答案,我可能在某个地方错了,不知道我的问题在哪里 这是我的示例类,我想测试它的方法 final class NavigationBuilder { @VisibleForTesting List<Intent> mIntentList = new ArrayList<>(5); @VisibleForTesting void addNextScreen

这是一个复制品。也有很多类似的问题/答案,但没有一个对我有帮助。由于有数百名开发人员接受了一些答案,我可能在某个地方错了,不知道我的问题在哪里

这是我的示例类,我想测试它的方法

final class NavigationBuilder {

    @VisibleForTesting List<Intent> mIntentList = new ArrayList<>(5);

    @VisibleForTesting
    void addNextScreenBasedOnBookingStatus(final Booking booking) {
        final ChatMsgDbAsyncHelper helper = new ChatMsgDbAsyncHelper();

        if (booking == null) {
            helper.cleanAllMessages(mContext); // <= Crash here
        } 

    }
}
测试失败,原因是
NullPointerException
,因为测试正在
helper.cleanAllMessages(mContext)内部运行逻辑。我对上面的模拟的期望是,这些逻辑不应该被执行

原因:java.lang.NullPointerException位于 ChatMessageTable.(ChatMessageTable.java:23)


给定代码中的逻辑是在传递mActivity对象时不执行任何操作:
PowerMockito.doNothing().when(spy).cleanalmessages(mActivity)

但您实际传递的是null:
mNavBuilder.addNextScreenBasedOnBookingStatus(null)

此外,您必须在测试类中传递这个“spy”对象,以使模拟逻辑工作。也许你可以试试这样的-

PowerMockito.whenNew(ChatMsgDbAsyncHelper.class).withNoArguments().thenReturn(spy);
PowerMockito.doNothing().when(spy).cleanAllMessages(mActivity); // or null, as per your requirement
然后将MacActivity对象传递给该方法:

mNavBuilder.addNextScreenBasedOnBookingStatus(mActivity); // or pass null, as per your requirement

问题在于我的理解:)

我用下面的代码更改了被测试方法的签名,并可以对其进行测试。因此,在本例中,我将
ChatMsgDbAsyncHelper
的实例传递给该方法,而不是在该方法中创建它

@VisibleForTesting
    void addNextScreenBasedOnBookingStatus(final Booking booking, final ChatMsgDbAsyncHelper chatMsgHelper) {
...
}
现在测试工作正常:

@Test
public void addNextScreenBasedOnBookingStatus_whenBookingIsNull() throws Exception {
    ChatMsgDbAsyncHelper mChatMsgHelper = PowerMockito.spy(new ChatMsgDbAsyncHelper());
    doNothing().when(mChatMsgHelper).cleanAllMessages(any(Context.class));

    mNavBuilder.addNextScreenBasedOnBookingStatus(null, mChatMsgHelper);

    assertTrue(mNavBuilder.mIntentList.isEmpty());
}

谢谢你的评论。是的,我实际上在那个链接中看到了类似的答案,并没有得到基于这种方法的测试后我所期望的结果。我不知道为什么,但没有工作,我得到了类似的输出,我在我的问题中提到。
@Test
public void addNextScreenBasedOnBookingStatus_whenBookingIsNull() throws Exception {
    ChatMsgDbAsyncHelper mChatMsgHelper = PowerMockito.spy(new ChatMsgDbAsyncHelper());
    doNothing().when(mChatMsgHelper).cleanAllMessages(any(Context.class));

    mNavBuilder.addNextScreenBasedOnBookingStatus(null, mChatMsgHelper);

    assertTrue(mNavBuilder.mIntentList.isEmpty());
}