【问题标题】:How to validate PreparedStatement scenario with Mockito. Unable to mock the PreparedStatement class in test class如何使用 Mockito 验证 PreparedStatement 场景。无法在测试类中模拟 PreparedStatement 类
【发布时间】:2021-03-16 14:29:03
【问题描述】:

我试图在测试类中模拟 PreparedStatement 类。我是这个单元测试用例实现的新手。有人可以指导我如何验证这种情况。

下面的代码是表单服务实现类。

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

以下代码来自测试类。 @嘲笑 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);

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

【问题讨论】:

    标签: java spring-boot unit-testing mocking mockito


    【解决方案1】:

    我在 ArgumentCaptor 的帮助下成功地测试了 PreparedStatementCreator。这样我们发送给查询方法的参数就会被捕获。随后,重写的方法被执行,我验证结果是否符合我们的预期。

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

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

    希望对大家有帮助。最好的问候

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多