Sunil
Sunil

Reputation: 121

Java Mockito is hitting real method rather than using mocked method

My mockito method is hitting the real method rather than invoking the mocked method. Your inputs will be helpful

Java code.

public class CheckUser {
    private final UserDao userDao;

    public CheckUser (final String domain){
        userDao = new UserDao(domain);
    }

    public IUser getExistingUser(){
            if (userDao == null) {
                throw new RuntimeException("userDao is null");
            }
            IUser existingUser = userDao.getExistingUser();
            if (existingUser == null) {
                throw new RuntimeException("ExistingUser is null");
            }
            return existingUser;
    }
}

This is my JUnit test code.

    @Test
    public void testExistingUser() {
        UserDao mockUserDao = mock(UserDao.class);
        when(mockUserDao.getExistingUser()).thenReturn(getExistingTestUser());
    }

    private UserDao getExistingTestUser(() {
        return ExistingUserImpl.Builder(). //withfield methods. build();
    }

I am creating this mock object for only testing purpose. This just return the mocked MockedExistingUserImpl object which is implemented by IUser.

public class MockedExistingUserImpl implements IUser {
    //fields
    //overriding getter methods for all fields
    //Builder for  ExistingUserImpl
}

When ever I call userDao.getExistingUser() in my code, I am expecting to return the mocked Existing user object but it is hitting the real method and failing the test due to domain connection. We don't establish a domain connection to run Junits. Any inputs are appreciated. Thank you !

Upvotes: 2

Views: 2238

Answers (2)

Bor Laze
Bor Laze

Reputation: 2516

Your mistake is in broken 'Dependency injection' principle.

Don't use new operator - create UserDao at the level above and use injection.

public class CheckUser {
    private final UserDao userDao;

    public CheckUser (final UserDao usedDao) {
        this.userDao = userDao;
    }

    public IUser getExistingUser() {
        if (userDao == null) {
            throw new RuntimeException("userDao is null");
        }
        IUser existingUser = userDao.getExistingUser();
        if (existingUser == null) {
            throw new RuntimeException("ExistingUser is null");
        }
        return existingUser;
    }
}

Now you can test your code in the following way:

@Test
public void testExistingUser() {
    UserDao mockUserDao = mock(UserDao.class);
    when(mockUserDao.getExistingUser()).thenReturn(getExistingTestUser());

    CheckUser checkUser = new CheckUser(mockUserDao);
    IUser iUser = checkUser.getExistingUser();

    // assertions here
}

private UserDao getExistingTestUser(() {
    return ExistingUserImpl.Builder(). //withfield methods. build();
}

Upvotes: 2

GhostCat
GhostCat

Reputation: 140623

The answer is to read a tutorial about Mockito and follow that. You make the typical mistake: you create a mock object, but then you don't do anything so that your production code uses that mocked object.

Just doing a mock(YourClass) doesn't magically change that new() in your production code to return a mocked instance.

You need to inject that mocked instance into the code under test. For example by using the @InjectMock annotation.

For a good intro, see https://www.baeldung.com/Mockito-annotations for example.

And note: as written right now, you will have a hard time to use Mockito for your tests. Due to the direct call to new(), you would need PowerMock(ito) to test it. So: learn how to use Mockito, and then rework your production code to be easily testable. (turning to PowerMock would be the wrong strategy).

Upvotes: 3

Related Questions