ArgumentCaptor捕获了错误的类

时间:2018-08-11 06:59:37

标签: android unit-testing testing mockito

已解决:即使Argument Captor上的getValue()向您显示了此信息,也是正常的。老实说,我期望在此处的OnLoginWithEmailCallback接口上看到实例。我这方面的问题与在mView上生成NPE的方法调用有关。现在就像魅力一样。

原始问题:

我正在MVP应用程序中使用Mockito来实现我的第一个单元测试,并且我需要在用户登录时模拟回调的行为。我正在使用Firebase处理身份验证。

我从这里遵循了一个很好的教程:https://fernandocejas.com/2014/04/08/unit-testing-asynchronous-methods-with-mockito/

我正在测试中的类上调用方法。此方法在Auth Presenter上调用另一个方法,该方法可以完成实际工作

mPresenter.performLoginWithEmail(EMAIL, PASSWORD);

然后,我正在验证Auth Presenter类中的下划线方法是否已被调用。我尝试捕获回调接口。

verify(mAuthPresenter, times(1)).login(mOnLoginWithEmailCallbackArgumentCaptor.capture(),
            eq(EMAIL), eq(PASSWORD));

问题是Argument Captor的getValue()返回了mPresenter(正在测试的类)的实例,而不是OnLoginWithEmailCallback接口类。因此,我得到了NPE。

mOnLoginWithEmailCallbackArgumentCaptor.getValue().onLoginWithEmailSuccess();

这是完整的测试课程:

@RunWith(MockitoJUnitRunner.class)  
public class LoginPresenterTest {  

    private static String EMAIL = "test@rmail.com";  
    private static String PASSWORD = "1234";  

    //class under test  
  private LoginPresenter mPresenter;  

    @Mock  
  AuthPresenter mAuthPresenter;  

    @Captor  
  private ArgumentCaptor<OnLoginWithEmailCallback> mOnLoginWithEmailCallbackArgumentCaptor;  

    @Mock  
  ILoginActivityView mView;  

    @Before  
  public void setupLoginPresenter() {  
        MockitoAnnotations.initMocks(this);  

        // Get a reference to the class under test  
  mPresenter = new LoginPresenter(mView, mAuthPresenter);  
    }  

    @Test  
  public void performLoginWithEmail() {  

        mPresenter.performLoginWithEmail(EMAIL, PASSWORD);  

        //wanting to have control over the callback object. therefore call capture to then call methods on the interface  
  verify(mAuthPresenter, times(1)).login(mOnLoginWithEmailCallbackArgumentCaptor.capture(),  
                eq(EMAIL), eq(PASSWORD));  

        mOnLoginWithEmailCallbackArgumentCaptor.getValue().onLoginWithEmailSuccess();  

        InOrder inOrder = Mockito.inOrder(mView);  
        inOrder.verify(mView).goToMap();  
        inOrder.verify(mView).hideProgressBar();  
    }  
}

编辑:这是对 mAuthPresenter.login 的调用:

已解决:getLoginActivityView()导致发生NPE

public void performLoginWithEmail(String email, String password) {  
    mAuthPresenter.login(new OnLoginWithEmailCallback() {  
        @Override  
  public void onLoginWithEmailSuccess() {  
            getLoginActivityView().goToMap();  
            getLoginActivityView().hideProgressBar();  
        }  

        @Override  
  public void onLoginWithEmailFailed(String error) {  
            getLoginActivityView().hideProgressBar();  
            getLoginActivityView().showToast(error);  
        }  
    }, email, password);  
}

我还尝试使用Mockito中的doAnswer:

    doAnswer(new Answer() {  
    @Override  
  public Object answer(InvocationOnMock invocation) throws Throwable {  
        ((OnLoginWithEmailCallback)invocation.getArguments()[0]).onLoginWithEmailSuccess();  
        return null;  
    }  
}).when(mAuthPresenter).login(  
        any(OnLoginWithEmailCallback.class, EMAIL, PASSWORD));

仍然,invocation.getArguments()返回被测类的一个实例(LoginPresenter),因此问题与以前相同。你能帮我吗?

1 个答案:

答案 0 :(得分:0)

问题是我被Argument Captor弄糊涂了,这使我返回了调用者类的实例(LoginPresenter)。在我的情况下,问题在于匿名类OnLoginWithEmailCallback()中的方法正在抛出NPE。