简体   繁体   English

如何使用 Mockito 验证 PreparedStatement 场景。 无法在测试 class 中模拟 PreparedStatement class

[英]How to validate PreparedStatement scenario with Mockito. Unable to mock the PreparedStatement class in test class

I am trying to mock the PreparedStatement class in test class.我试图在测试 class 中模拟 PreparedStatement class。 I am new to this Unit testcases implementation.我是这个单元测试用例实现的新手。 Can someone guide me how to validate this scenario.有人可以指导我如何验证这种情况。

Below code is form service impl class.下面的代码是表单服务 impl class。

String sqlToUpdateDeploymentTable = UPDATE_DEPLOYMENT_BY_REQUEST_ID_FOR_APPROVE_AND_REJECT;

        getJdbcTemplate().update(sqlToUpdateDeploymentTable, request.getApprover(), request.getApproverComment(),
                request.isApproved() ? APPROVED : REJECTED, Timestamp.from(Instant.now()), request.getRequestId());

        String sqlToUpdateDeploymentAprrovalTable = INSERT_RECORD_INTO_DEPLOYMENT_APPROVAL;
        getJdbcTemplate().update(new PreparedStatementCreator() {
            public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
                PreparedStatement ps = connection.prepareStatement(sqlToUpdateDeploymentAprrovalTable);
                ps.setString(1, request.getApprover());
                ps.setString(2, request.getRequestId());
                return ps;
            }
        });

        if (request.isApproved()) {
            return DEPLOYEMNET_REQUEST + AppConstants.REQ_PREFIX + request.getRequestId() + HAS_BEEN_APPROVED;
        }

Below code is from test class.下面的代码来自测试 class。 @Mock JdbcTemplate jdbcTemplate; @Mock JdbcTemplate jdbcTemplate;

@Mock
Connection connection;

@Mock
PreparedStatementCreator statementcreator;

@Mock
PreparedStatement statement;

    sql = "Some Sql query"
    RequestDto requestDto = new RequestDto();
    requestDto.setRequestId("123445");
    String APPROVED = "approved";
    
    String query = "UPDATE db.code SET approval_time="
            + Timestamp.from(Instant.now()) + " WHERE request_id=" + requestDto.getRequestId();

    
    Mockito.when(jdbcTemplate.update(new PreparedStatementCreator() {
        statement.createPreparedStatement(Connection connection) throws SQLException {
            PreparedStatement ps = connection.prepareStatement(query);
            ps.setString(2, requestDto.getRequestId());
            return ps;
        }
    })).thenReturn(1);

    Mockito.when(jdbcTemplate.update(query,Timestamp.from(Instant.now()), requestDto.getRequestId())).thenReturn(0);
    //Mockito.when(PreparedStatement(statement).createPreparedStatement(connection)).thenReturn(statement);

    String response = utilimpl.approverReject(requestDto, errors);
    System.out.println(response);

In test class i am not able to enter into the PreparedStatementCreator block.在测试 class 中,我无法进入 PreparedStatementCreator 块。 I mocked all the required class in test class.我在测试 class 中模拟了所有必需的 class。 I am not sure where i am missing.我不确定我在哪里失踪。

I managed to test PreparedStatementCreator with the help of ArgumentCaptor.在 ArgumentCaptor 的帮助下,我设法测试了 PreparedStatementCreator。 So that the arguments that we send to the query method are captured.这样我们发送给查询方法的arguments就被捕获了。 Subsequently, the overridden method is executed and I verify that the result is as we expected.随后,执行覆盖的方法,我验证结果是否符合我们的预期。

@ExtendWith(MockitoExtension.class)
class PostgresJdbcAdapterTest {     
    private PostgreJdbcRepository repository;
    @Mock
    private JdbcTemplate template;
    @Mock
    private DataSource dataSource;
    @Mock
    private Connection conn;
    @Mock
    private PreparedStatement stmt;

    @BeforeEach
    void init() {
        repository = new PostgresJdbcAdapter(dataSource);
        ReflectionTestUtils.setField(repository, "template", template);
    }

    @Test
    void when_customReportQuery_then_result() throws SQLException {
        ArgumentCaptor<PreparedStatementCreator> creatorCaptor = ArgumentCaptor.forClass(PreparedStatementCreator.class);
        ArgumentCaptor<ReportRowCallbackHandler> handlerCaptor = ArgumentCaptor.forClass(ReportRowCallbackHandler.class);

        repository.customReportQuery(request);

        BDDMockito.given(conn.prepareStatement(anyString())).willReturn(stmt);
        verify(template).query(creatorCaptor.capture(), handlerCaptor.capture());
        PreparedStatementCreator creator = creatorCaptor.getValue();
        creator.createPreparedStatement(conn);

        verify(stmt).setString(1, request.getParam());

        ReportRowCallbackHandler handler = handlerCaptor.getValue();
        ResultSet rs = mock(ResultSet.class);
        handler.processRow(rs);

        Assertions.assertThat(repository.customReportQuery(request)).isEmpty();
    }
}

The class PostgresJdbcAdapter class PostgresJdbcAdapter

@Repository
public class PostgresJdbcAdapter extends JdbcDaoSupport implements ReportPostgreJdbcRepository {
    private static final String RESULT_MESSAGE = "JDBC - POSTGRES - Query: with {} records";
    private static final String EXCEPTION_MESSAGE = "JDBC - POSTGRES - Error trying to execute query: {}";
    
    private final JdbcTemplate template;
    
    @Autowired
    public PostgresJdbcAdapter(DataSource dataSource) {
        this.template = new JdbcTemplate(dataSource);
        setDataSource(dataSource);
    }
    
    @Override
    public List<ReportRow> customReportQuery(ReportRequest request) {
        String sql = "SELECT * FROM table WHERE table.name = ?";
        
        PreparedStatementCreator creator = conn -> {
            PreparedStatement stmt = conn.prepareStatement(sql);
            stmt.setString(1, request.getName());
            
            return stmt;
        };
        try {
            ReportRowCallbackHandler handler = new ReportRowCallbackHandler();
            template.query(creator, handler);
            log.info(RESULT_MESSAGE, handler.getResult().size());
            return handler.getResult();
        } catch (DataAccessException ex) {
            log.error(EXCEPTION_MESSAGE, ex.getMessage());
            throw new PostgreJdbcException(ex);
        }
    }
}

and the row handler和行处理程序

public class ReportRowCallbackHandler implements RowCallbackHandler {

    private final List<ReportRow> result = new LinkedList<>();


    @Override
    public void processRow(ResultSet rs) throws SQLException {
        ReportRow row = ReportRow.builder()
            .name(rs.getString("name"))
            .build();

        result.add(row);
    }

    public List<ReportRow> getResult() {
        return Collections.unmodifiableList(result);
    }
}

I hope it helps everyone.我希望它对每个人都有帮助。 Best regards此致

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM