【问题标题】:How to mock a void method with PowerMockito?如何使用 PowerMockito 模拟 void 方法?
【发布时间】:2017-07-06 15:04:56
【问题描述】:

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

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

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


    【解决方案1】:

    您在给定代码中的逻辑是当您传递 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
    

    【讨论】:

    • 感谢您的评论。是的,我实际上在该链接中看到了类似的答案,并且在基于这种方法进行测试后没有得到我期望的结果。我不知道为什么但没有工作,我得到了我在问题中提到的类似输出。
    【解决方案2】:

    问题是我的理解:)

    我用以下方法更改了被测方法的签名并可以对其进行测试。所以在这种情况下,我将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());
    }
    

    【讨论】:

      猜你喜欢
      • 2014-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多