如何使用 PowerMockito 模拟 void 方法?

问题描述 投票:0回答:2

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

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

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
        } 

    }
}

这是我的测试课:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ChatMsgDbAsyncHelper.class, SplashActivity.class})
public class NavigationBuilderTest {

    private SplashActivity mActivity;
    private NavigationBuilder mNavBuilder;

    @Before
    public void setUp() throws Exception {

        mActivity = new SplashActivity();
        ISplashView view = mock(ISplashView.class);
        PassengerStorage passengerStorage = mock(PassengerStorage.class);

        mNavBuilder = new NavigationBuilder(mActivity, view, passengerStorage);
    }

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

        mNavBuilder.addNextScreenBasedOnBookingStatus(null);

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

测试失败,原因是

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

原因:java.lang.NullPointerException at com.xxx.xxx.db.entities.ChatMessageTable.(ChatMessageTable.java:23)

java android unit-testing powermockito spy
2个回答
0
投票

给定代码中的逻辑是在传递 mActivity 对象时不执行任何操作:

PowerMockito.doNothing().when(spy).cleanAllMessages(mActivity);

但是你实际传递的内容是空的:

mNavBuilder.addNextScreenBasedOnBookingStatus(null);

此外,您必须在测试类中传递这个“间谍”对象才能使您的模拟逻辑正常工作。也许你可以尝试这样的事情 -

PowerMockito.whenNew(ChatMsgDbAsyncHelper.class).withNoArguments().thenReturn(spy);
PowerMockito.doNothing().when(spy).cleanAllMessages(mActivity); // or null, as per your requirement

然后将你的 mActivity 对象传递给该方法:

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

0
投票

问题在于我的理解:)

我用以下方法更改了被测方法的签名并可以对其进行测试。因此,在这种情况下,我将

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());
}
© www.soinside.com 2019 - 2024. All rights reserved.