Reputation: 261
I wrote a test case but I get a null pointer exception at the return KeyHolder.getKey()
line.
My test case looks like this:
@InjectMocks
private UserDAOImpl userDAO;
@Mock
private JdbcTemplate jdbcTemplate;
@Mock
private KeyHolderFactory keyHolderFactory;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
ReflectionTestUtils.setField(userDAO, "jdbcTemplate", jdbcTemplate);
}
@Test
public void testCreateUser() {
KeyHolder keyHolder = mock(GeneratedKeyHolder.class);
when(keyHolderFactory.newKeyHolder()).thenReturn(keyHolder);
User user = getUserInfo();
Map<String,Object> map = new HashMap<>();
map.put("id",1L);
when(keyHolder.getKeys()).thenReturn(map);
when(keyHolder.getKey()).thenReturn(1L);
when(jdbcTemplate.update(Mockito.any(PreparedStatementCreator.class), Mockito.any(KeyHolder.class))).thenReturn(1);
assertEquals(1L, userDAO.createUser(user));
}
And the method looks like this:
@Override
public long createUser(User user) {
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(connection -> {
PreparedStatement ps = connection
.prepareStatement("insert into user (address, first_name,last_name, email, password, phone_number, is_init, is_system_admin, created_at)"
+ " values( ?, ?, ?, ?, ?, ?, ?, ?,?)",
Statement.RETURN_GENERATED_KEYS);
ps.setString(1, user.getAddress());
ps.setString(2, user.getFirstName());
ps.setString(3, user.getLastName());
ps.setString(4, user.getEmail());
ps.setString(5, user.getPassword());
ps.setString(6, user.getPhone());
ps.setBoolean(7, user.isActive());
ps.setBoolean(8, user.isSystemAdmin());
ps.setDate(9, new Date(Date.from((user.getCreatedAt().toInstant())).getTime()));
return ps;
}, keyHolder);
return (long) keyHolder.getKey();
}
I have created an interface KeyHolderFactory
:
public interface KeyHolderFactory {
KeyHolder newKeyHolder();
}
And the implementation of this interface is as follows:
public class GeneratedKeyHolderFactory implements KeyHolderFactory {
public KeyHolder newKeyHolder() {
return new GeneratedKeyHolder();
}
}
Can someone help me to find a solution?
Upvotes: 3
Views: 2855
Reputation: 313
Your issue is next :
In test class you have Mocked bin KeyHolderFactory
and this is correct. Then you create mocked KeyHolder
, describe it's behavior and make KeyHolderFactory
return KeyHolder
when it is asked. Everything looks OK except next :
On your code class method you create new KeyHolder
using new GeneratedKeyHolder()
and this new KeyHolder
doesn't relate to those mocked instance that you have in your test class. It is absolutely different objects. That one which is in your test class - is a mock, and will follow your scenario. But that one, in your tested class method, is another object, which of course don't know what to do when you execute keyHolder.getKey()
.
Solution :
You have injected KeyHolderFactory
in your test and well configured it's behavior. Just inject this into your test class as well and use it in your method to create KeyHolder
using keyHolderFactory.newKeyHolder()
instead of new GeneratedKeyHolder()
Upvotes: 3