samedi 11 août 2018

ArgumentCaptor captures wrong class

I am implementing my first unit test using Mockito in my MVP app and I need to mock the behaviour of a callback when the user is logging in. I am using Firebase to handle the authentication.

I followed a very good tutorial from here : https://fernandocejas.com/2014/04/08/unit-testing-asynchronous-methods-with-mockito/.

I am calling method on class under test. This method calls another one on the Auth Presenter which does the actual work

mPresenter.performLoginWithEmail(EMAIL, PASSWORD);

Then I am verifying that an underlining method in the Auth Presenter class was called. I try to capture the callback interface.

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

The problem is that getValue() from the Argument Captor returns an instance of the mPresenter (class under test) instead of the OnLoginWithEmailCallback interface class. Therefore I get an NPE.

mOnLoginWithEmailCallbackArgumentCaptor.getValue().onLoginWithEmailSuccess();

Here is the complete test class:

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

I also tried using using doAnswer from Mockito:

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

Still, invocation.getArguments() return an instance of the class under test (LoginPresenter), so the same problem as before. Can you help me?

Aucun commentaire:

Enregistrer un commentaire