Home > front end >  how to test method with resultSet and preparedStatement
how to test method with resultSet and preparedStatement

Time:10-11

i would like to unit test my method, which return from database id of last inserted object:

     public int getLastId() throws SQLException {
        String query = "select LAST_INSERT_ID();";
        PreparedStatement stmt = connection.prepareStatement(query);
        int id = -1;
        ResultSet resultSet = stmt.executeQuery();
        while (resultSet.next()) {
            id = resultSet.getInt("LAST_INSERT_ID()");
        }
        return id;
    }

and then i want to do same unit test like this:

    dataBaseService = mock(DataBaseService.class);
        resultSet = mock(ResultSet.class);

     @Test
    public void getLastIdIsCorrect() throws SQLException {
        //given
        int expectedId = 1;
        int expectedIncorrectId = 101;
        //when
        when(resultSet.getInt("LAST_INSERT_ID()")).thenReturn(1);
        when(dataBaseService.getLastId()).thenCallRealMethod();
        int result = dataBaseService.getLastId();
        //then
        Assert.assertEquals(expectedId, result);
        Assert.assertNotEquals(expectedIncorrectId, result);
    }

But i'm getting Null pointer exception at line with PreparedStatement stmt = connection.prepareStatement(query);

Can you explain me please, how to do unit tests like this correctly? I have few methods left with the same problem and i'm still learning unit tests....

CodePudding user response:

The problem is, that you seem to be unclear what you are testing. If you are testing the code of getLastId then you should not mock the class containing it - DataBaseService - normally. Instead, your test would be a test OF DataBaseService with something like this...

Connection connection = mock(Connection.class);
PreparedStatement stmt = mock(PreparedStatement.class);

...and...

when(connection.prepareStatement(Mockito.anyString())).thenReturn(stmt);
when(stmt.executeQuery()).thenReturn(resultSet);

When you are outside of DataBaseService and want to test something that's calling it, then you can mock DataBaseService and simply return a number then. But for testing DataBaseService it's not needed to do something like...

dataBaseService = mock(DataBaseService.class);
...
when(dataBaseService.getLastId()).thenCallRealMethod();

Simply create a new instance of DataBaseService and mock the things "inside" it, for example the Connection.

To show some more code, it would be required to know the setup of your class and also which JUnit version you are using.

CodePudding user response:

Ok, thx for your answer :) i've changed and created DataBaseService object, and then tried to mock everything inside like this:

@Test
public void getLastIdIsCorrect() throws SQLException {
    //given
    int expectedId = 1;
    int expectedIncorrectId = 101;
    //when
    when(DriverManager.getConnection(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(connection);
    when(connection.prepareStatement(Mockito.anyString())).thenReturn(stmt);
    when(stmt.executeQuery()).thenReturn(resultSet);
    int result = dataBaseService.getLastId();
    //then
    Assert.assertEquals(expectedId, result);
    Assert.assertNotEquals(expectedIncorrectId, result);
}

and now i'm getting that exception and headache too :D :

com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
  • Related