簡體   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