I am testing a DAO class using JUnit and I am getting a nullpointerexception which I am not sure why as I am initiating the service class. The following is the test class:
public class RegisterTest {
private UserDaoImpl userservice = new UserDaoImpl();
#Mock
JdbcTemplate jdbcTemplate;
User user;
#Before
public void setUp() {
user = new User();
}
#Test
public void testSetAddress() {
user.setAddress("A");
assertEquals(user.getAddress(), "A");
}
#Test
public void testSetEmail() {
user.setEmail("B");
assertEquals(user.getEmail(), "B");
}
#Test
public void testSetFirstname() {
user.setFirstname("C");
assertEquals(user.getFirstname(), "C");
}
#Test
public void testSetLastname() {
user.setLastname("D");
assertEquals(user.getLastname(), "D");
}
#Test
public void testSetPassword() {
user.setPassword("E");
assertEquals(user.getPassword(), "E");
}
#Test
public void testSetUsername() {
user.setUsername("F");
assertEquals(user.getUsername(), "F");
}
#Test
public void testRegister() {
userservice.register(user);
String username = user.getUsername();
assertEquals(userservice.findByUsername(username), 1);
}
}
The following is the UserDaoImpl
public class UserDaoImpl implements UserDao {
#Autowired
PasswordEncoder passwordEncoder;
#Autowired
DataSource datasource;
#Autowired
JdbcTemplate jdbcTemplate;
public List<User> findByUsername(String username) {
String sql = "select * from users where username='" + username +
"'";
List<User> users = jdbcTemplate.query(sql, new UserMapper());
return users;
}
public int register(User user) {
// If username is unique
String uniqueusername = "select * from users where username='" +
user.getUsername() + "'";
List<User> users = jdbcTemplate.query(uniqueusername, new
UserMapper());
if(users.size() == 0) {
// encode password
String encryptedPassword =
passwordEncoder.encode(user.getPassword());
// Updating database with new user
String sql = "insert into users values(?,?,?,?,?,?)";
return jdbcTemplate.update(sql, new Object[] {
user.getUsername(),
encryptedPassword,
user.getFirstname(),
user.getLastname(),
user.getEmail(),
user.getAddress() });
}
else {
return 0;
}
}
How can I inject the class in the test class? I guess the reason why the nullpointerxeception is because the dao class is not being injected properly in the test class
You should run your test with adequate runner
RunWith(MockitoJunitRunner.class)
public class RegisterTest {
Then you need to inject your mock inside the DAO
#InjectMocks
private UserDaoImpl userservice = new UserDaoImpl();
Related
I have problem with NullPointerException, every POST on /register endpoint, the NullPointerException shows that service is null
Controller with /register
#AllArgsConstructor
#RestController
#Validated
public class SecurityController {
private final UserService service;
#PostMapping("/register")
private ResponseEntity<UserDTO> registerUser (#RequestBody #Valid RegisterDTO registerDTO) {
return ResponseEntity.created(URI.create("/user")).body(service.createUser(registerDTO));
}
UserService
#RequiredArgsConstructor
#Service
public class UserService implements UserServiceApi {
private final UserRepository userRepository;
private final RoleRepository roleRepository;
private final PasswordEncoder encoder;
#Override
public UserDTO createUser(RegisterDTO user) {
if (user.equals(userRepository.findByUsername(user.getUsername()))) {
throw new RuntimeException("This nickname is already taken");
}
if (user.equals(userRepository.findByEmail(user.getEmail()))) {
throw new RuntimeException("This email is already taken");
}
// Encoding password
user.setPassword(encoder.encode(user.getPassword()));
// On creating new Account it's going to have USER role
Role role = roleRepository.findByName("USER");
String username = user.getUsername();
String password = user.getPassword();
String email = user.getEmail();
User dto = buildUser(username, password, email, role);
userRepository.save(dto);
return UserDTO.builder()
.username(username)
.password(password)
.email(email)
.build();
}
Other controller that use service, I dont know maybe that's the cuase of problem
#RestController(value = "/user")
#AllArgsConstructor
#Validated
public class UserController {
private final UserService service;
#GetMapping("/getusers")
public ResponseEntity<List<User>> getAllUser() {
return ResponseEntity.ok(service.getUsers());
}
I am new to Spring boot, I have tried to check with unregistered emailID whether the given email id is available or not in the Postgres database. But unfortunately got this NoSuchElementException. I have attached an exception screenshot here for your reference. Can you guys help me to come out of this problem?.
TipTopController.java
#RestController
#RequestMapping(path = "/user")
public class TipTopController {
#Autowired
private UserService userService;
#PostMapping(path = "/registration")
public ResponseEntity<UserRegistrationResponse> registration(#RequestBody UserRegistrationModel userRegistrationModel){
UserRegistrationResponse userRegistrationResponse = userService.doUserRegistration(userRegistrationModel);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("description","User created successfully");
return ResponseEntity.status(HttpStatus.OK)
.headers(httpHeaders)
.body(userRegistrationResponse);
}
}
UserService.java
#Service
public class UserService {
private static final Logger logger = LogManager.getLogger(UserService.class);
#Autowired
private UserRepository userRepository;
#Transactional
public UserRegistrationResponse doUserRegistration(UserRegistrationModel userRegistrationModel){
UserRegistrationResponse userRegistrationResponse = new UserRegistrationResponse();
try{
logger.info("Entering into try block");
Optional<UserInformationRepo> userInformationRepo=userRepository.findById(userRegistrationModel.getEmail());
logger.info("Get value is "+userInformationRepo.get().getEmail());
logger.info("Username is "+userInformationRepo.get().getFirstName()+" "+userInformationRepo.get().getLastName());
if(userInformationRepo.isPresent()){
userRegistrationResponse.setStatus(false);
userRegistrationResponse.setMessage("This email id { "+userRegistrationModel.getEmail()+" } is taken by another user already");
}
else{
UserInformationRepo userInformationRepoSave = new UserInformationRepo();
userInformationRepoSave.setEmail(userRegistrationModel.getEmail());
userInformationRepoSave.setFirstName(userRegistrationModel.getFirstName());
userInformationRepoSave.setEmail(userRegistrationModel.getLastName());
userInformationRepoSave.setEmail(userRegistrationModel.getPassword());
userRepository.save(userInformationRepoSave);
userRegistrationResponse.setStatus(true);
userRegistrationResponse.setMessage("New user account created with your " + userRegistrationModel.getEmail() + " emailId");
}
}
catch (Exception e){
logger.error(e.getMessage()+"*****"+e);
System.out.println("Exception occurred");
}
return userRegistrationResponse;
}
}
UserInformationRepo.java
#Entity
#Table(name = "USER_INFORMATION")
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
public class UserInformationRepo {
#Id
#Column(name = "EMAIL")
private String email;
#Column(name="FIRSTNAME")
private String firstName;
#Column(name="LASTNAME")
private String lastName;
#Column(name="PASSWORD")
private String password;
}
UserRepository.java
#Repository
public interface UserRepository extends JpaRepository<UserInformationRepo, String> {
}
This is the exception I got while tried to hit the registration API from POSTMAN tool
Are you sure that com.ajithan.tiptop.tiptopapplication.domain.UserInformationRepo is a correct fully qualified class name?
Are you sure that the entity UserInformationRepo has an appropriate constructor for this:
UserInformationRepo(UI.EMAIL,UI.FIRSTNAME,UI.LASTNAME,UI.PASSWORD)
You should not use a native query for this. You can use JPA query in this way:
#Transactional
#Query(value = "select new com.ajithan.tiptop.tiptopapplication.domain.UserInformationRepo(UI.email,UI.firstName,UI.lastName,UI.password) from UserInformationRepo UI where UI.email = :email")
UserInformationRepo checkUserExists(#Param("email") String email);
Why you can't just use the standard method?
Optional<UserInformationRepo> findById(String id);
You can avoid to use your custom methods checkUserExists and saveNewUser and start to use the standard JpaRepository methods findById and save in this way:
#Transactional
public UserRegistrationResponse doUserRegistration(UserRegistrationModel userRegistrationModel)
{
UserRegistrationResponse userRegistrationResponse = new UserRegistrationResponse(); // this was missed !!!
try{
logger.info("Entering into try block");
Optional<UserInformationRepo> userInformationRepo = userRepository.findById(userRegistrationModel.getEmail());
System.out.println(userInformationRepo.getEmail());
if(userInformationRepo.isPresent()){
userRegistrationResponse.setStatus(false);
userRegistrationResponse.setMessage("This email id { "+userRegistrationModel.getEmail()+" } is taken by another user already");
}
else{
UserInformationRepo userInfo = new UserInformationRepo();
userInfo.setEmail(userRegistrationModel.getEmail());
userInfo.setFirstName(userRegistrationModel.getFirstName())
userInfo.setLastName(userRegistrationModel.getLastName());
userInfo.setPassword(userRegistrationModel.getPassword());
userRepository.save(userInfo);
userRegistrationResponse.setStatus(true);
userRegistrationResponse.setMessage("New user account created with your " + userRegistrationModel.getEmail() + " emailId");
}
}
catch (Exception e){
logger.error(e.getMessage()+"*****"+e);
System.out.println("Exception occurred");
}
return userRegistrationResponse;
}
I have task to upgrade Map based storage to DB based storage. My project configuration is based on annotations. Could you explain to me which steps should I take to make it happen? And how will change my dao layer code:
public class TicketDao {
Set<Ticket> tickets = new HashSet<>();
public Set<Ticket> getAll() {
return tickets;
}
public void remove(Ticket ticket){
tickets.remove(ticket);
}
public void put(Ticket ticket){
tickets.add(ticket);
}
}
Create db and schema
Configure DataSource and JdbcTemplate. The simpliest configuration:
#Configuration
public class JdbcConfig {
#Bean
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("");
dataSource.setUrl("");
dataSource.setUsername("");
dataSource.setPassword("");
return dataSource;
}
#Bean
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource());
}
}
Inject JdbcTemplate into dao and use it
public class TicketDao {
public static final String DELETE_QUERY = "delete from Ticket where id = ?";
public static final String INSERT_QUERY = "insert into Ticket values(?, ?)";
public static final String GET_ALL_QUERY = "select * from Tickets";
#Autowired
JdbcTemplate jdbcTemplate;
public Set<Ticket> getAll() {
return new HashSet<>(jdbcTemplate.query(GET_ALL_QUERY, new RowMapper<Ticket>() {
#Override
public Ticket mapRow(ResultSet rs, int rowNum) throws SQLException {
Ticket ticket = new Ticket();
ticket.setId(rs.getString(1));
//other fields mapping
return ticket;
}
}));
}
public void remove(Ticket ticket){
jdbcTemplate.update(new PreparedStatementCreator() {
#Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement statement = con.prepareStatement(DELETE_QUERY);
statement.setString(1, ticket.getId());
return statement;
}
});
}
public void put(Ticket ticket){
Object[] values = {ticket.getId(), ticket.getName()};
int[] types = {Types.VARCHAR, Types.VARCHAR};
jdbcTemplate.update(INSERT_QUERY, values, types);
}
}
this is my code:
my model class:
#Entity
#Table(name="admin")
public class Admin extends Profile{
public Admin(){}
public Admin(String mail, String name, String lastName, String password, Date birthDate, int gsm){
super(mail, name, lastName, password, birthDate, gsm);
}
}
the DAO class:
#Repository
public class AdminDAO {
private static final Logger logger = LoggerFactory.getLogger(AdminDAO.class);
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf){
this.sessionFactory = sf;
}
#SuppressWarnings("unchecked")
public List<Admin> listAdmins() {
Session session = this.sessionFactory.getCurrentSession();
List<Admin> adminsList = session.createQuery("from Admin").list();
for(Admin a : adminsList){
logger.info("Admin List::"+a);
}
return adminsList;
}
}
my Service class:
#Service
public class AdminService {
#Autowired
private AdminDAO adminDAO;
public void setAdminDAO(AdminDAO adminDAO) {
this.adminDAO = adminDAO;
}
#Transactional
public List<Admin> listAdmins() {
return this.adminDAO.listAdmins();
}
}
when i run my code i get this error message:
java.lang.NullPointerException
at com.journaldev.spring.dao.AdminDAO.listAdmins(AdminDAO.java:38)
i added an admin manually in my database, but it still showing the null pointer exception
what i am doing wrong ??
note: i have another class that works fine, it gets all entities and when the database is empty, it doesn't generate null pointer exception
You missed the #Autowired or the #Inject annotation for the setter method for adminDAO. It has to be
#Autowired
public void setAdminDAO(AdminDAO adminDAO) {
this.adminDAO = adminDAO;
}
You have to annotate all dependencies of your Bean with #Autowired or #Inject.
I've got a method which returns me a ResultSet object:
#Repository
public class SomeDAOImpl implements SomeDAO{
#Override
public ResultSet getSomething()
{
...
}
}
And this is how I call that:
#Service
public class SomeServiceImpl implements SomeService{
#Autowired
private SomeDAO someDAO;
#Transactional
#Override
public void doSomething()
{
someDAO.getSomething();
...
}
}
Questions:
Do I have to close ResultSet?
Is it ok to return ResultSet object?
1 Yes you should close a ResultSet.
2 I suggest you to return an Object and not a ResultSet.
Here a draft as should be... Here a tutorial.
#Repository
public class SomeDAOImpl implements SomeDAO{
#Override
public User getSomething(String username){
User user = getJdbcTemplate().queryForObject("SELECT * FROM USER WHERE USERNAME = ?",
new Object[] { username },
new UserMapper()
);
return user;
}
private class UserMapper implements RowMapper<User>{
#Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt("ID"));
user.setUsername(rs.getString("USERNAME"));
user.setName(rs.getString("NAME"));
return user;
}
}
}