【问题标题】:how to test handler.postDelayed with mockito?如何用 mockito 测试 handler.postDelayed?
【发布时间】:2017-05-09 09:43:51
【问题描述】:

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

    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 之后是否可以点击。

如何实施这种测试?

【问题讨论】:

    标签: android unit-testing mockito


    【解决方案1】:

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

    Handler mockHandler = mock(Handler.class);
    when(mockHandler.postDelayed(any(Runnable.class), anyLong())).thenAnswer(new Answer() {
    
        @覆盖
        公共对象答案(InvocationOnMock 调用)抛出 Throwable {
            invocation.getArgumentAt(0, Runnable.class).run();
            返回空值;
        }
    
    });

    【讨论】:

      【解决方案2】:

      我在模拟最终的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());
      

      【讨论】:

        【解决方案3】:

        我遇到了同样的问题,但在我的情况下,我真的应该用实际的 delay 运行实际的 Runnable,所以基于 @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;
            });
        

        【讨论】:

          【解决方案4】:

          在 kotlin 中只需使用下面的

          val handler: Handler = mock(Handler::class.java)
          

          Runnable.postDelayed() ->

           `when`(handler.postDelayed(any(Runnable::class.java), anyLong())).thenAnswer {
                      (it.arguments[0] as Runnable).run()
                      true
                  }
              
          

          Runnable.post() ->

          `when`(handler.post(any(Runnable::class.java))).thenAnswer {
                      (it.arguments[0] as? Runnable)?.run()
                      true
                  }
          

          进口

          import org.mockito.ArgumentMatchers
          import org.mockito.Mockito.*
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-03-06
            • 2021-04-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-04-07
            • 2014-01-18
            相关资源
            最近更新 更多