0

Lately I have been trying to test my Spring Boo(2.0.3) Service, but I have been receiving a NullPointerException. The userDAOImpl implements the userDAO interface,

Here is the serviceImpl class, it implements the interface Service:

import app.clothapp.DAO.UserDAO;
import app.clothapp.Model.User;
import app.clothapp.Service.UserService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class UserServiceImpl implements UserService {
    Logger logger = LogManager.getLogger("UserServiceImplLogger");


    @Autowired
    private UserDAO userDao;



    @Override
    @Transactional
    public void createUser(User user) {
        logger.debug("Creating an user " + UserServiceImpl.class.getName());
        userDao.addUser(user);
    }

    @Override
    public void deleteUserById(int id) {
        logger.debug("Deleting an user " + UserServiceImpl.class.getName());
        userDao.deleteUserById(id);
    }

    @Override
    public List<User> getUsersByEmail(String email) {
        logger.debug("Getting a list of users by email" + UserServiceImpl.class.getName());
        return userDao.findUsersByEmail(email);
    }

    @Override
    public void changeUserPassword(User user, String newPassword) {
        logger.debug("Changing a user's password " + UserServiceImpl.class.getName());
        userDao.changeUserPassword(user, newPassword);
    }

    @Override
    public void changeUserFirstName(User user, String firstName) {
        logger.debug("Changing an user's first name" + UserServiceImpl.class.getName());
        userDao.changeUserFirstname(user, firstName);
    }

    @Override
    public void changeUserLastname(User user, String lastname) {
        logger.debug("Changing an user's last name" + UserServiceImpl.class.getName());
        userDao.changeUserLastname(user, lastname);
    }

    @Override
    public void changeUserEmail(User user, String email) {
        logger.debug("Changing an user's email" + UserServiceImpl.class.getName());
        userDao.changeUserEmail(user, email);
    }

    @Override
    public List<User> findAllUsers() {
        logger.debug("Finding all users" + UserServiceImpl.class.getName());
        return userDao.findAllUsers();
    }
}

Here's my UserDAOImpl.

import app.clothapp.DAO.UserDAO;
import app.clothapp.Model.User;
import app.clothapp.Model.User.UserFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

//import static org.apache.logging.log4j.Level.ALL;
//import static org.apache.logging.log4j.Level.DEBUG;
//import static org.apache.logging.log4j.Level.WARN;




@Repository
@Qualifier("UserDAO")
public class UserDAOImpl implements UserDAO {


    @Autowired
    JdbcTemplate jdbcTemplate;
    Logger logger = LogManager.getLogger("Log");



    @Override
    public void addUser(User user) {
        logger.debug(UserDAOImpl.class.getName() + ": addUser() creating user");
        if (findUsersByEmail(user.getEmail()).isEmpty() == false) {
            logger.debug(UserDAOImpl.class.getName() + ":addUser() denied user creation because of email duplicate!");
        } else {
            jdbcTemplate.update("INSERT INTO User(firstName, lastName, Email, Password) VALUES (?, ?, ?, ?) ", user.getFirstname(), user.getLastname(), user.getEmail(), user.getPassword());
            logger.debug(UserDAOImpl.class.getName() + ": addUser() User created!");

        }

    }

    @Override
    public void changeUserPassword(User user, String password) {
        jdbcTemplate.update("UPDATE User SET Password = ? WHERE Id = ?", password, user.getId());
        logger.debug(UserDAOImpl.class.getName() + "User changed password. ");
    }

    @Override
    public void changeUserFirstname(User user, String firstName) {
        jdbcTemplate.update("UPDATE User SET Firstname = ? WHERE Id = ?", firstName, user.getId());
        logger.debug(UserDAOImpl.class.getName() + "User changed the first name.");
    }

    @Override
    public void changeUserLastname(User user, String lastname) {
        jdbcTemplate.update("UPDATE User SET Lastname = ? Where Id = ?", lastname, user.getId());
        logger.debug(UserDAOImpl.class.getName() + "User changed last name.");
    }

    @Override
    public void changeUserEmail(User user, String email) throws RuntimeException {
        if (findUsersByEmail(email).isEmpty() == false) {
            System.out.println(UserDAOImpl.class.getName() + "There is already a user within the database that has that email.");
            throw new RuntimeException(UserDAOImpl.class.getName() + "There is already a user within the database that has that email.");
        } else {
            jdbcTemplate.update("UPDATE User SET Email = ? Where Id = ?", email, user.getId());
            logger.debug(UserDAOImpl.class.getName() + new StringBuilder().append("User").append(user.getFirstname()).append("email was changed.").toString());
        }
    }

    @Override
    public void deleteUserById(int id) {
        logger.debug("Deleted user with user ID" + id + UserDAOImpl.class.getName());
        jdbcTemplate.update("DELETE from User WHERE Id = ?", id);
    }

    @Override
    public List<User> findUsersByEmail(String email) {
        logger.debug(UserDAOImpl.class.getName() + "found users by email using foundUsersByEmail()");
        return jdbcTemplate.query("SELECT * FROM User where Email = ?", new UserRowMapper(), email);
    }


    @Override
    public List<User> findAllUsers() {
        logger.debug(UserDAOImpl.class.getName() + "found all Users");
        return jdbcTemplate.query("SELECT * FROM User", new UserRowMapper());

    }

    public class UserRowMapper implements RowMapper<User> {
        public User mapRow(ResultSet resultSet, int rowNumber) throws SQLException {
            UserFactory userFactory = new User.UserFactory()
                    .setId(resultSet.getInt("id"))
                    .setFirstname(resultSet.getString("Firstname"))
                    .setLastname(resultSet.getString("Lastname"))
                    .setPassword(resultSet.getString("Password"))
                    .setEmail(resultSet.getString("Email"));

            User user = userFactory.build();
            return user;
        }
    }
}

Here is my JUnit 5 Spring Boot test:

@RunWith(SpringJUnit4ClassRunner.class)

class UserServiceTest {

User user = new User.UserFactory().setFirstname("Firs")
        .setLastname("Las")
        .setEmail("[email protected]")
        .setPassword("paaaaaaa")
        .build();

@Mock
private JdbcTemplate jdbcTemplate = new JdbcTemplate();

@InjectMocks
private UserServiceImpl userService;


@Mock
private UserDAO userDAO;

@BeforeEach
void setUp() {

    MockitoAnnotations.initMocks(this.getClass());



}

@Test
void createUser() {
    Mockito.doNothing().when(userDAO).addUser(user);
    userService.createUser(user);

    Mockito.when(userService.findAllUsers().get(0)).thenReturn(user);

    assertEquals(userService.findAllUsers().get(0), user);
}

@Test
void deleteUserById() {
}

@Test
void getUsersByEmail() {
}

@Test
void changeUserPassword() {
}

@Test
void changeUserFirstName() {
}

@Test
void changeUserLastname() {
}

@Test
void changeUserEmail() {
}

@Test
void findAllUsers() {
}

}

As you can see, I create an user utilizing the UserFactory, mock the jdbcTemplate and userDAOImpl, then inject them into the UserServiceImpl(). THen within the createUser() test, I create the user with the service, and set up the Mockito.when, and test if the user is there within the database.

However, I receive a NullPointerException, though I am not sure why. Could anyone provide me with a hint?

EDIT: I have now received a NullInsteadOfMock error, I have to instanstantiate the UserDAO object, but UserDAO is an interface!

org.mockito.exceptions.misusing.NullInsteadOfMockException: 
Argument passed to when() is null!
Example of correct stubbing:
    doThrow(new RuntimeException()).when(mock).someMethod();
Also, if you use @Mock annotation don't miss initMocks()

    at app.clothapp.ServiceImpl.UserServiceTest.createUser(UserServiceTest.java:55)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:513)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:170)
    at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:166)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:113)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:58)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:113)
    at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:121)
    at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
    at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
    at java.util.Iterator.forEachRemaining(Iterator.java:116)
    at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
    at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:121)
    at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:121)
    at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
    at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
    at java.util.Iterator.forEachRemaining(Iterator.java:116)
    at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
    at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:121)
    at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:55)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:74)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

2 Answers 2

1

Your Mockito code is a little off. Instead of instantiating UserServiceImpl with new, you should just have the InjectMocks annotation. UserDao should be mocked instead of UserDaoImpl. Before you call UserService.createUser, you should set a mocked for UserDao.createUser to do nothing when called.

2
  • Hi, I have received a NullInsteadOfMockException. Could it be due to the lack of the @Autowire annotation?
    – Octalc
    Commented Jul 27, 2018 at 19:39
  • @Autowired is ignored in a mocked class and completely ignored in the unit test. Where is the exception being thrown?
    – Yserbius
    Commented Jul 30, 2018 at 2:06
0

To use the @Mock annotation you need to use

@RunWith(MockitoJUnitRunner.class)

Instead of

@RunWith(SpringJUnit4ClassRunner.class)

So your mocks are created correctly.

Also in this line:

@Mock
private JdbcTemplate jdbcTemplate = new JdbcTemplate();

You need to remove the new because you want mockito to create and manage a mock instance of that class. Like this:

@Mock
private JdbcTemplate jdbcTemplate;
2
  • Hi; do you know why it currently says userDAO is null in my doNothing().when()..?
    – Octalc
    Commented Jul 28, 2018 at 2:19
  • @Octalc because you are using the wrong class to run your test. Reread my answer and change the runner class. Commented Jul 31, 2018 at 18:59

Not the answer you're looking for? Browse other questions tagged or ask your own question.