【问题标题】:how to verify the function is called inside Runnable::run()如何验证函数在 Runnable::run() 中被调用
【发布时间】:2021-01-26 19:11:02
【问题描述】:

有一个带有函数runInMainThread(Handler mainHandler) 的类,它执行一些可运行的run():

class AppLifecycleObserver implements LifecycleObserver {

    protected Context mAppContext;

    AppLifecycleObserver(@NonNull Context appContext) {
        mAppContext = appContext;
    }

    Lifecycle getLifeCycle() {
        return ProcessLifecycleOwner.get().getLifecycle();
    }

    void runInMainThread(Handler mainHandler) {
        Runnable myRunnable = new Runnable() {
            @Override
            public void run() {
                getLifeCycle().addObserver(AppLifecycleObserver.this);  // needed to verify it's called
            }
        };
        mainHandler.post(myRunnable);
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public void onStart() {
        // do something
    }
}

在单元测试中,想验证getLifeCycle().addObserver(AppLifecycleObserver.this);是否被调用。

尝试关注但出现错误。

@RunWith(RobolectricTestRunner.class)
public class AppLifecycleObserverTest {
    private Context mContext;

    @Before
    public void setup() {
        mContext = RuntimeEnvironment.application;
    }

    @Test
    public void test_runInMainThread() throws Exception{

        AppLifecycleObserver appLifecycleObserver2 = spy(new AppLifecycleObserver(mContext));
        Lifecycle lifecycle = spy(appLifecycleObserver2.getLifeCycle());
        doReturn(lifecycle).when(appLifecycleObserver2).getLifeCycle();

        Handler handler = mock(Handler.class);
        final CountDownLatch finished = new CountDownLatch(1);

        doAnswer(new Answer() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
                finished.countDown();
                return null;
            }
        }).when(appLifecycleObserver2).runInMainThread(handler);

        appLifecycleObserver2.runInMainThread(handler);
        finished.await(2, TimeUnit.SECONDS);

        verify(lifecycle).addObserver(appLifecycleObserver2);

    }
}

得到错误(似乎它没有等待 Runnable::run() 被调用):

java.lang.Exception: Main looper has queued unexecuted runnables. This might be the cause of the test failure. You might need a shadowOf(getMainLooper()).idle() call.

        at org.robolectric.android.internal.AndroidTestEnvironment.checkStateAfterTestFailure(AndroidTestEnvironment.java:470)
        at org.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:548)
        at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$0(SandboxTestRunner.java:252)
        at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:89)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
        Caused by: Wanted but not invoked:
        lifecycleRegistry.addObserver(
        AppLifecycleObserver$$EnhancerByMockitoWithCGLIB$$c0ef6f97@62eadb96
        );
        -> at ppLifecycleObserverTest.test_runInMainThread(AppLifecycleObserverTest.java:133)
        Actually, there were zero interactions with this mock.


【问题讨论】:

    标签: android unit-testing junit mockito runnable


    【解决方案1】:

    这行得通,一定有更好的:

    @Test
        public void test_runInMainThread() throws Exception{
            
            // test the Runnable::run(), the addObserver() should be called
            AppLifecycleObserver appLifecycleObserver2 = spy(new AppLifecycleObserver(mContext));
            Lifecycle lifecycle = spy(ProcessLifecycleOwner.get().getLifecycle());
    
            doReturn(lifecycle).when(appLifecycleObserver2).getLifeCycle();
    
            Handler handler = mock(Handler.class);
            final CountDownLatch finished = new CountDownLatch(1);
    
            Mockito.when(handler.post(Mockito.any(Runnable.class))).thenAnswer(
                    new Answer<Object>() {
                        @Override
                        public Object answer(InvocationOnMock invocation) throws Throwable {
                            Runnable msg = invocation.getArgumentAt(0, Runnable.class);
                            msg.run();
                            finished.countDown();
                            return null;
                        }
                    }
            );
    
            appLifecycleObserver2.runInMainThread(handler);
            finished.await(2, TimeUnit.SECONDS);
            verify(lifecycle).addObserver(appLifecycleObserver2);
            
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-22
      • 1970-01-01
      相关资源
      最近更新 更多