如何对我收到正确的 PreparedStatement 进行单元测试?

Ami*_*iko 1 java junit unit-testing mocking mockito

我想将合适的对象传入验证方法,而不仅仅是 any()。

有没有办法做到这一点?

我不能只是采用和复制 Lambda 方法并将结果传递给验证。这不起作用,因为无法直接测试 Lambda。

我的单元测试显然还没有接近测试任何东西:

    @Test
public void testRunTrigger() {
    campaignTrigger.updateCampaignStatus();

    verify(jdbcTemplate).update(any(PreparedStatementCreator.class));
    assertEquals("UPDATE campaign SET state = 'FINISHED'  WHERE state IN ('PAUSED','CREATED','RUNNING') AND campaign_end < ? ", campaignTrigger.UPDATE_CAMPAIGN_SQL);
}
Run Code Online (Sandbox Code Playgroud)

这是我正在测试的课程:

@Component
@Slf4j
public class CampaignTrigger {
final String UPDATE_CAMPAIGN_SQL = String.format("UPDATE campaign SET state = '%s' " +
                " WHERE state IN (%s) AND campaign_end < ? ", FINISHED,
        Stream.of(PAUSED, CREATED, RUNNING)
                .map(CampaignState::name)
                .collect(Collectors.joining("','", "'", "'")));

@Autowired
private JdbcTemplate jdbcTemplate;

@Scheduled(cron = "${lotto.triggers.campaign}")
@Timed
void updateCampaignStatus() {
    jdbcTemplate.update(con -> {
        PreparedStatement callableStatement = con.prepareStatement(UPDATE_CAMPAIGN_SQL);
        callableStatement.setTimestamp(1,  Timestamp.valueOf(LocalDateTime.now()));
        log.debug("Updating campaigns statuses.");
        return callableStatement;
    });
}
Run Code Online (Sandbox Code Playgroud)

任何建议或理论知识表明这不是这样做的方法,我将不胜感激。

Jar*_*lak 5

您不应该嘲笑您无法控制的代码。只模拟你有测试的代码,因为在模拟时你假设你知道(即你定义)被模拟的类是如何工作的。

在这里,你不知道它是如何jdbcTemplate工作的,也不知道用一些 lambda 调用它是否真的像你认为的那样做。

使用您无法控制的代码测试您的代码是集成测试的重点。即你应该CampaignTrigger用一个真实的数据库(或内存数据库)来测试你的数据库,而不是模拟jdbcTemplate

  • 我同意模拟外部系统行为,但我认为在您的单元测试中使用模拟来检查与该系统的交互是否符合您的期望,例如 `verify(mockConnection).prepareStatement(expectedSQL)`。这允许在提交之前运行一些单元测试(应该很快),除了偶尔执行一次的集成测试(通常很慢)。 (2认同)