javalambdamockitofunctional-interface

Mocked method inside lambda expression is not working


I am using the mockito but connection.prepareStatement is not getting matched and I am getting null as PreparedStatement. I have checked connection is getting mocked properly

void myMethod(){
    getJdbcTemplate().update(connection -> {
            PreparedStatement ps = connection.prepareStatement(addEmailData, new String[] { "mail_id" });
            ps.setString(++i, mailBean.getFromEmailId());

            return ps;
        }, keyHolder);
}

Below is the test case written

    void test(){
        when(connection.prepareStatement(anyString(),any(String[].class))).thenReturn(mock(PreparedStatement.class));
        when(dataSource.getConnection()).thenReturn(connection);
        myClass.init(dataSource);
        // Act
        myClass.myMethod(); 
    }

Can someone please advise how to return prepareStatement so that calls on PS can be tested


Solution

  • In fact, when testing the myMethod() method, you have to test the PreparedStatementCreator interface implementation, which is created by the connection -> { ... } lambda expression when calling the JdbcTemplate.update() method. To do this, you must capture the argument with which this method is called, so that you can then call it with a mock Connection implementation.

    For example, you can do this.

    Create mock implementations of the Connection, JdbcTemplate, and PreparedStatement interfaces.

    Connection connection = Mockito.mock(Connection.class);
    JdbcTemplate jdbcTemplate = Mockito.mock(JdbcTemplate.class);
    PreparedStatement preparedStatement = Mockito.mock(PreparedStatement.class);
    

    Create a captor for the PreparedStatementCreator implementation that is created in your method.

    ArgumentCaptor<PreparedStatementCreator> preparedStatementCreatorCaptor = ArgumentCaptor.forClass(PreparedStatementCreator.class);
    

    Define the behavior of a mock Connection implementation when the Connection.prepareStatement() method is called.

    Mockito.when(connection.prepareStatement(Mockito.anyString(), Mockito.any(String[].class))).thenReturn(preparedStatement);
    

    Execute your method with a mock JdbcTemplate implementation.

    MyClass myClass = new MyClass(jdbcTemplate);
    myClass.myMethod();
    

    Make sure your method calls JdbcTemplate.update() and capture the PreparedStatementCreator implementation.

    Mockito.verify(jdbcTemplate).update(preparedStatementCreatorCaptor.capture(), Mockito.any(KeyHolder.class));
    

    Make sure that this PreparedStatementCreator implementation creates the exact PreparedStatement that your Connection returns.

    Assertions.assertEquals(preparedStatement, preparedStatementCreatorCaptor.getValue().createPreparedStatement(connection));