【问题标题】:How to mock and verify a callback in method using Mockito如何使用 Mockito 模拟和验证方法中的回调
【发布时间】:2017-07-01 17:27:02
【问题描述】:

在这个方法中,我想模拟并确保在我没有传入某个电子邮件字符串时调用mSharedPrefsManager

@Override
public void retrieveWithEmail(final String email, final WelcomeContract.Presenter presenter)
{
    retrieveInteractor.buildRetrieveRequest(email, new RetrieveImpl.OnRetrieveCompletedListener()
    {
        @Override
        public void onRetrieveCompleted(final MaitreBaseGson retrieveResponse, RetrieveImpl retrieveClass)
        {
            if (retrieveResponse.getStatus().equals(mContext.getString(R.string.ok)))
            {
                if (!email.equals("certain@email.com"))
                    mSharedPrefsManager.storePoints(Integer.parseInt(retrieveResponse.getData().getPoints()));
                presenter.updateSilhouette(retrieveResponse);
            }
            // Silently swallow failures
        }
    });
}

但是,通过我的测试,我无法确定是否调用了 mSharedPrefsManager。 Mockito 说 .storePoints() 永远不会被调用。我想过做一个doReturn().when(),但因为这是行不通的方法,不是吗?

如何捕捉sharedPrefsManager 上的互动?

Mockito 还说 .updateSilhouette() 没有被调用。我需要以某种方式模拟 onRetrieveCompleted() 吗?

@RunWith(MockitoJUnitRunner.class)
public class WelcomeInteractorTest
{
    @Mock
    RetrieveImpl retrieveInteractor;

    @Mock
    WelcomePresenter welcomePresenter;

    @Mock
    SharedPrefsManager sharedPrefsManager;

    @Mock
    Context context;

    @InjectMocks WelcomeInteractorImpl welcomeInteractor;

    @Mock
    RetrieveImpl.OnRetrieveCompletedListener onRetrieveCompletedListener;

    @Test
    public void RetrieveWithCertainEmail_SavePoints()
    {
        welcomeInteractor.retrieveWithEmail("certain@email.com", welcomePresenter);
        verify(retrieveInteractor).buildRetrieveRequest(eq("certain@email.com"), any(RetrieveImpl.OnRetrieveCompletedListener.class));
        verify(sharedPrefsManager).storePoints(any(Integer.class));
        verify(welcomePresenter).updateSilhouette(any(MaitreBaseGson.class));
    }
}

【问题讨论】:

  • 你能发布你的代码是如何结束的吗?

标签: android unit-testing mockito


【解决方案1】:

RetrieveImpl 与网络交互时,尝试使用@Spy 给我带来了很多问题。

我改为使用Captor 并捕获回调。

@Captor
private ArgumentCaptor<RetrieveImpl.OnRetrieveCompletedListener> mOnRetrieveCompletedListenerCaptor;

...

@Test
public void isTest()
{
    ...
    verify(retrieveInteractor).buildRetrieveRequest(eq(email), mOnRetrieveCompletedListenerCaptor.capture());
    mOnRetrieveCompletedListenerCaptor.getValue().onRetrieveCompleted(mockMaitreBaseGsonSuccessful, retrieveInteractor);
}

【讨论】:

    【解决方案2】:

    你在嘲讽:

    @Mock
    RetrieveImpl retrieveInteractor;
    

    这意味着当您调用retrieveInteractor.buildRetrieveRequest(..) 时,不会调用真正的实现,并且最终您希望在该方法调用中调用的方法永远不会被调用..

    尝试改用@Spy,这实际上将允许调用真正的实现,并且您还可以验证该对象:

    @Spy
    RetrieveImpl retrieveInteractor;
    

    只是一方面..认为您在那里进行了太多测试并深入验证。

    我认为应该为 RetrieveImpl.OnRetrieveCompletedListener 类进行该测试。不是您的问题。

    但这只是我的口味..

    【讨论】:

    • 我的 RetrieveImplContext 作为其构造函数中的唯一参数,Mockito 给我一个错误,说它需要一个 0-arg 构造函数。我可以以某种方式模拟Context,还是需要采用不同的方法?
    • 添加一个默认的构造函数和上下文的设置器。然后模拟 Context 并使用 setter 注入 RetrieveImpl
    猜你喜欢
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 2019-01-06
    • 2012-08-09
    • 2013-10-18
    • 1970-01-01
    • 1970-01-01
    • 2020-09-30
    相关资源
    最近更新 更多