繁体   English   中英

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

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

我试图在测试 class 中模拟 PreparedStatement 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;
        }

下面的代码来自测试 class。 @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);

在测试 class 中,我无法进入 PreparedStatementCreator 块。 我在测试 class 中模拟了所有必需的 class。 我不确定我在哪里失踪。

在 ArgumentCaptor 的帮助下,我设法测试了 PreparedStatementCreator。 这样我们发送给查询方法的arguments就被捕获了。 随后,执行覆盖的方法,我验证结果是否符合我们的预期。

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

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

和行处理程序

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

我希望它对每个人都有帮助。 此致

暂无
暂无

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

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