简体   繁体   中英

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 !

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM