如何测试handler.postDeleyed与mockito?

时间:2017-05-09 09:43:52

标签: android unit-testing mockito

我是单元测试的新手,我坚持测试以下方法:

    fun freeze(view: View) {
        view.isClickable = false
        handler.postDelayed({
             view.isClickable = true
        }, CLICK_TIMEOUT)
    }

以下是我已经拥有的内容:

    @Test
    fun freeze() {
        var view = mock<View>()
        viewUtil.freeze(view)
        assertFalse(view.isClickable)
    }

但现在我需要在CLICK_TIMEOUT之后测试该视图是否可以点击。

我该如何实施这种测试?

3 个答案:

答案 0 :(得分:4)

如果你能够模拟Handler实例,你可以这样做:

Handler mockHandler = mock(Handler.class);
when(mockHandler.postDelayed(any(Runnable.class), anyLong())).thenAnswer(new Answer() {

    @Override
    public Object answer(InvocationOnMock invocation) throws Throwable {
        invocation.getArgumentAt(0, Runnable.class).run();
        return null;
    }

});

答案 1 :(得分:0)

我在模拟最终的postDelayed方法时遇到了麻烦,但是由于它归结为非最终的sendMessageAtTime,所以我对此进行了模拟。使用spy避免模拟其他Handler方法。

spyHandler = spy(new Handler(getMainLooper()));
doAnswer(new Answer() {
        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            Message message = invocation.getArgument(0);
            message.getCallback().run();
            return true;
        }
    }).when(spyHandler).sendMessageAtTime(any(Message.class), anyLong());

答案 2 :(得分:0)

我遇到了同样的问题,但就我而言,我应该使用实际的Runnable来运行实际的delay,因此基于@mrtowel答案,我最终得到了以下代码:

 Handler handler = mock(Handler.class);
 when(handler.postDelayed(any(Runnable.class), anyLong())).thenAnswer((Answer) invocation -> {
        new Thread(() -> {
            try {
                Thread.sleep(invocation.getArgument(1));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ((Runnable) invocation.getArgument(0)).run();
        }).start();
        return null;
    });