简体   繁体   English

如何验证 function 在 Runnable::run() 中被调用

[英]how to verify the function is called inside Runnable::run()

having a class with a function runInMainThread(Handler mainHandler) , which execute something it a runable's run():有一个 class 和一个 function 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
    }
}

in the unit test, would like to verify that getLifeCycle().addObserver(AppLifecycleObserver.this);在单元测试中,想验证getLifeCycle().addObserver(AppLifecycleObserver.this); is called.叫做。

tried following but got error.尝试关注但出现错误。

@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);

    }
}

got error (seems it does not wait the Runnable::run() gets called):得到错误(似乎它不等待 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.


this works, there must be better ones:这行得通,必须有更好的:

@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);
        
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM