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)