Mockito:没有调用传递给方法的Runnable参数的Runnable.run()

时间:2017-05-05 07:19:08

标签: android mockito

我正在和Mockito一起测试。我有一个回调界面:

interface Callback {
    void onMessageRetrieved(String message);
    void onRetrievalFailed(String error);
}

然后,我有一个方法接受调用该Callback方法的Runnable对象:

首先,interactor.run()调用调用postMessage的方法:

    @Override
    public void run() {
        final String message = mMessageRepository.getWelcomeMessage();
        if (message == null || message.length() == 0) {
            notifyError();
            return;
        }
        postMessage(message);
    }

    private void postMessage(final String msg) {
    mMainThread.post(new Runnable() {
        @Override
        public void run() {
            mCallback.onMessageRetrieved(msg);
        }
    });
}

但是行mCallback.onMessageRetrieved(msg);永远不会被执行,所以我得到了:

 Wanted but not invoked:
 callback.onMessageRetrieved(
     "Welcome, friend!"
 );

为什么run()没有执行?

我正在使用此articles项目。这是我的Test类:

public class ExampleUnitTest {    
    private MessageRepository mMessageRepository;
    private Executor mExecutor;
    private MainThreadImpl mMainThread;
    private WelcomingInteractor.Callback mMockedCallback;

    @Before
    public void setUp() {
        mMessageRepository = mock(MessageRepository.class);
        mExecutor = mock(Executor.class);
        mMainThread = mock(MainThreadImpl.class);
        mMockedCallback = mock(WelcomingInteractor.Callback.class);
    }

    @Test
    public void testWelcomeMessageFound() throws Exception {
        String msg = "Welcome, friend!";
        when(mMessageRepository.getWelcomeMessage()).thenReturn(msg);
        WelcomingInteractorImpl interactor = new WelcomingInteractorImpl(
                mExecutor,
                mMainThread,
                mMockedCallback,
                mMessageRepository);
        interactor.run();

        Mockito.verify(mMessageRepository).getWelcomeMessage();
        Mockito.verifyNoMoreInteractions(mMessageRepository);
        Mockito.verify(mMockedCallback).onMessageRetrieved(msg);
    }
}

1 个答案:

答案 0 :(得分:1)

下面:

data = [];
result.forEach(function(i) { data.push({label: i.x, value: i.y}) });
Morris.Donut({
      element: 'graph_donut',
      data: data,
      resize: true
    });

但是在你的单元测试中,你有:

mMainThread.post(new Runnable()

该post()调用会收到 Runnable 对象。我假设你的impl类在某个帖子中运行 Runnable.run()。

但是:在您的单元测试中,您嘲笑所有这些元素。

您必须明白:mExecutor = mock(Executor.class); mMainThread = mock(MainThreadImpl.class); 不会创建真正的 MainThreadImpl对象。它会返回看起来的内容,就像该类的对象一样;但这是模拟。它与您的实际实现完全解耦。当你做mMainThread = mock(MainThreadImpl.class);时......什么都不会发生。 运行方法从不执行。因为当您在其上调用mMainThread.poll()时,模拟对象对该参数执行

换句话说:您必须配置所有模拟。例如,您可以使用ArgumentCaptor和捕获给予post()方法的Runnable对象。

但是,当然,因为这只是一个匿名内部类的一些实例,这无济于事。

长话短说:你应该退一步;并进一步阅读如何/为何使用模拟对象...