Пересмешивание Dateformat (SimpleDateFormat) в тестах JUnit - PullRequest
0 голосов
/ 05 июня 2018

Я пытаюсь проверить функцию DAO, которая использует DateFormat (SimpleDateFormat).Когда я пытаюсь запустить тест, я получаю:

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)

Это указывает на :lection.setStartDate (df.format (rs.getDate ("startDate")));в DAO

Это тестовый код:

@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");
    }
}

Это функция в 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;
    }

Я попробовал несколько примеров, которые нашелонлайн, но я все еще получаю ту же ошибку.Я также прочитал, что DateFormat является конечной функцией и не может быть поддельным.Там, где некоторые обходные пути, но у меня не сработало.Я не уверен, что правильно реализовал эти обходные пути.

Не могли бы вы предоставить мне код для исправления этого NullPointer?Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 05 июня 2018

Прежде всего, я не вижу ничего насмешливого над rs.getDate (), так что он будет возвращать ноль.Это, вероятно, вызовет проблемы как с поддельными, так и с реальными экземплярами SimpleDateFormat.Вы можете адресовать это следующим образом:

// (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);

Это вместе when(formatter.format(any())).thenReturn("'2018-11-12 00:00'") может преодолеть исключение.Похоже, однако, что вы создаете настоящий SimpleDateFormat внутри AdminDaoImpl, а ваш поддельный не привыкнет вообще.Поэтому вам придется либо изменить AdminDaoImpl, чтобы позволить вам вводить SimpleDateFormat, либо написать свои тесты, чтобы они не знали, что AdminDaoImpl использует SimpleDateFormat.

Лично я бы не стализдеваться над SimpleDateFormat на всех.Вместо этого я бы рассматривал это как внутреннюю деталь реализации AdminDaoImpl.Я бы посмеялся над набором результатов, чтобы вернуть дату, а затем проверил, что ElectionListResponse имеет ожидаемую дату.Это выглядело бы примерно так:

// (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());

Эти тесты подтверждают, что Election правильно сопоставил startDate из набора результатов, но им совершенно все равно, как AdminDaoImpl делает это,

0 голосов
/ 05 июня 2018

Если вы издеваетесь над DateFormat, тогда зачем вы создаете объект SimpleDateFormat.Вы должны предоставить when () и thenReturn () везде, где вы используете объект SimpleDateFormat.Все зависимости должны быть смоделированы, никакого реального создания объекта там не было бы.

В ходе модульного тестирования DAO не было бы никакого взаимодействия с базой данных, вы можете легко смоделировать слой db.

when(df.format("your_date").thenReturn(some_value);
...