Im trying to test a DAO function which uses a DateFormat (SimpleDateFormat). When I try to run the test im getting:
java.lang.NullPointerException
at java.util.Calendar.setTime(Calendar.java:1770)
at java.text.SimpleDateFormat.format(SimpleDateFormat.java:943)
at java.text.SimpleDateFormat.format(SimpleDateFormat.java:936)
at java.text.DateFormat.format(DateFormat.java:345)
This points to : election.setStartDate(df.format(rs.getDate("startDate"))); in the DAO
This it the test code:
@RunWith(MockitoJUnitRunner.class)
public class AdminDaoImplTest {
@Mock
Connection mockConn;
@Mock
PreparedStatement mockPreparedStmnt;
@Mock
ResultSet mockResultSet;
@Mock
DateFormat formatter;
@InjectMocks
private AdminDao adminDao = new AdminDaoImpl();
@Mock
private SQLConnection mockSqlConnection;
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void init() throws SQLException {
when(mockSqlConnection.getConnection()).thenReturn(mockConn);
when(mockConn.prepareStatement(anyString())).thenReturn(mockPreparedStmnt);
when(mockPreparedStmnt.executeQuery()).thenReturn(mockResultSet);
when(mockResultSet.next()).thenReturn(Boolean.TRUE, Boolean.FALSE);
when(formatter.format(any())).thenReturn("'2018-11-12 00:00'");
}
@After
public void tearDown() {
}
@Test
public void testGetElectionsNoExceptions() throws SQLException {
ElectionListResponse electionListResponse = new ElectionListResponse();
adminDao.getElections('>' );
//verify and assert
verify(mockConn, times(1)).prepareStatement(anyString());
verify(mockPreparedStmnt, times(1)).executeQuery();
verify(mockResultSet, times(1)).next();
verify(mockResultSet, times(1)).getInt("id");
verify(mockResultSet, times(1)).getString("name");
verify(mockResultSet, times(1)).getDate("startDate");
verify(mockResultSet, times(1)).getDate("endDate");
}
}
This is the function in the DAO:
@Override
public ElectionListResponse getElections(char selector) {
ElectionListResponse electionListResponse = new ElectionListResponse();
String query = NamedQueries.GET_ELECTIONS_BEGIN + selector + NamedQueries.GET_ELECTIONS_END;
try {
con = sqlConnection.getConnection();
stmt = con.prepareStatement(query);
rs = stmt.executeQuery();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
while (rs.next()) {
Election election = new Election();
election.setElectionID(rs.getInt("id"));
election.setElectionName(rs.getString("name"));
election.setStartDate(df.format(rs.getDate("startDate")));
election.setEndDate(df.format(rs.getDate("endDate")));
electionListResponse.addElection(election);
}
return electionListResponse;
} catch (SQLException e) {
LOGGER.log(Level.SEVERE, "Cant get elections. ", e);
} finally {
closeConnection();
}
return null;
}
I have tried some examples i've found online, but I'm still getting the same error. I also have read that DateFormat is a final function and cannot be mocked. There where some workarounds, but didn't work for me. I'm not sure I've implemented those workaround correctly.
Could you please provide me the code to fix this NullPointer? Thanks in advance!
First of all, I don't see anything mocking rs.getDate() so that is going to return null. That will probably cause problems with both mocked and real instances of SimpleDateFormat
. You can address that like this:
// (I am using the deprecated constructor for simplicity)
java.sql.Date startDate = new java.sql.Date(2018, 6, 5);
Mockito.when(mockResultSet.getDate("startDate")).thenReturn(startDate);
That combined when(formatter.format(any())).thenReturn("'2018-11-12 00:00'")
might get you past the exception. It looks, though, like you are creating a real SimpleDateFormat
inside AdminDaoImpl
and your mocked one wouldn't get used at all. So you will have to either modify AdminDaoImpl
to allow you to inject the SimpleDateFormat
or write your tests so that they do not know that AdminDaoImpl
uses SimpleDateFormat
.
Personally, I wouldn't mock the SimpleDateFormat at all. Instead, I would treat it as an internal implementation detail of AdminDaoImpl
. I would mock the result set to return the date and then verify that the ElectionListResponse
has the expected date. That would look something like this:
// (I am using the deprecated constructor for simplicity)
java.sql.Date startDate = new java.sql.Date(2018, 6, 5);
Mockito.when(mockResultSet.getDate("startDate")).thenReturn(startDate);
ElectionListResponse response = adminDao.getElections('>' );
Election firstElection = response.getFirst() // Or whatever method(s) get you the first one
Assert.assertEquals("2018-06-05 00:00", firstElection.getStartDate());
These tests confirm that the Election
has its startDate
mapped properly from the result set, but they don't care at all how AdminDaoImpl
does it.
If you're mocking DateFormat then why you're creating SimpleDateFormat object. You should provide when() and thenReturn() wherever you're using SimpleDateFormat object. All the dependencies should be mocked, no actual object creation would be there.
No database interaction would be there while unit testing of DAO, you can easily mock the db layer.
when(df.format("your_date").thenReturn(some_value);
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.