Search code examples
androidjunitmockitojunit4

Mockito and callback returning "Argument(s) are different!"


I'm trying to use mockito on android. I want to use it with some callback. Here my test :

public class LoginPresenterTest {


private User mUser = new User();

@Mock
private UsersRepository mUsersRepository;

@Mock
private LoginContract.View mLoginView;

/**
 * {@link ArgumentCaptor} is a powerful Mockito API to capture argument values and use them to
 * perform further actions or assertions on them.
 */
@Captor
private ArgumentCaptor<LoginUserCallback> mLoadLoginUserCallbackCaptor;

private LoginPresenter mLoginPresenter;

@Before
public void setupNotesPresenter() {
    // Mockito has a very convenient way to inject mocks by using the @Mock annotation. To
    // inject the mocks in the test the initMocks method needs to be called.
    MockitoAnnotations.initMocks(this);

    // Get a reference to the class under test
    mLoginPresenter = new LoginPresenter(mUsersRepository, mLoginView);

    // fixtures
    mUser.setFirstName("Von");
    mUser.setLastName("Miller");
    mUser.setUsername("von.miller@broncos.us");
    mUser.setPassword("Broncos50superBowlWinners");
}

@Test
public void onLoginFail_ShowFail() {

    // When try to login
    mLoginPresenter.login("von.miller@broncos.us", "notGoodPassword");


    // Callback is captured and invoked with stubbed user
    verify(mUsersRepository).login(eq(new User()), mLoadLoginUserCallbackCaptor.capture());
    mLoadLoginUserCallbackCaptor.getValue().onLoginComplete(eq(mUser));

    // The login progress is show
    verify(mLoginView).showLoginFailed(anyString());
}

But I got this error :

Argument(s) are different! Wanted:
mUsersRepository.login(
    ch.example.project.Model.User@a45f686,
    <Capturing argument>
);
-> at example.ch.project.Login.LoginPresenterTest.onLoginFail_ShowFail(LoginPresenterTest.java:94)
Actual invocation has different arguments:
mUsersRepository.login(
    ch.example.project.Model.User@773bdcae,
    ch.example.project.Login.LoginPresenter$1@1844b009
);

Maybe the issue is that the second actual argument is ch.example.project.Login.LoginPresenter$1@1844b009 ?

I followed : https://codelabs.developers.google.com/codelabs/android-testing/#5

Thank you for help =)

Edit

The method I try to test (LoginPresenter):

@Override
public void login(String email, String password) {

    mLoginView.showLoginInProgress();

    User user = new User();
    user.setUsername(email);
    user.setPassword(password);

    mUsersRepository.login(user, new UsersRepository.LoginUserCallback() {

        @Override
        public void onLoginComplete(User loggedUser) {
            mLoginView.showLoginComplete();
        }

        @Override
        public void onErrorAtAttempt(String message) {
            mLoginView.showLoginFailed(message);
        }
    });

}

Solution

  • eq(new User())
    

    When using eq (or not using matchers at all), Mockito compares arguments using the equals method of the instance passed in. Unless you've defined a flexible equals implementation for your User object, this is very likely to fail.

    Consider using isA(User.class), which will simply verify that the object instanceof User, or any() or anyObject() to skip matching the first parameter entirely.