如何使用Mockito模拟和验证使用回调函数的方法

3
在这种方法中,我希望模拟并确保在我不传入某个特定的电子邮件字符串时调用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));
    }
}

你能分享一下你是如何完成你的代码吗? - Caique
2个回答

1

尝试使用@Spy对我造成了很多问题,因为RetrieveImpl与网络进行交互。

我改用了Captor并捕获了回调。

@Captor
private ArgumentCaptor<RetrieveImpl.OnRetrieveCompletedListener> mOnRetrieveCompletedListenerCaptor;

...

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

0

你正在嘲笑:

@Mock
RetrieveImpl retrieveInteractor;

这意味着当您调用retrieveInteractor.buildRetrieveRequest(..)时,实际实现不会被调用,最终您期望在该方法调用中调用的方法也不会被调用。
尝试使用@Spy代替,这将允许实际实现被调用,并且您还可以验证该对象:
@Spy
RetrieveImpl retrieveInteractor;

就我的理解,你在测试上花费了太多的时间,并且深入到验证中了。

我认为应该对RetrieveImpl.OnRetrieveCompletedListener类进行测试。而不是你提出问题的那个类。

但这只是我的个人看法。


我的 RetrieveImpl 在其构造函数中只接受 Context 作为唯一参数,但是 Mockito 给出了一个错误,说它需要一个无参构造函数。我能否以某种方式模拟 Context,或者我需要遵循不同的方法? - Josh Laird
1
添加一个默认构造函数和Context的setter。然后模拟Context并使用setter注入到RetrieveImpl中。 - Maciej Kowalski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接