You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Awaitility验证事件未发生?现有实现报错求解

问题分析与解决方案

问题根源

你的代码逻辑存在两个核心问题:

  1. 条件判断写法冗余易混淆:通过findFirst().orElse(null)再匹配nullValue的方式,本质是判断“无匹配记录”,但这种写法不如直接用noneMatch语义明确,也容易在Awaitility的条件校验中产生歧义。
  2. 对during方法的理解偏差:during(Duration)的作用是验证条件在指定时长内持续成立,而非“等待一段时间后检查条件”。错误信息显示条件当前值符合预期(expected null but was null),但Awaitility未完成“条件持续满足15秒”的要求,因此抛出超时异常。

正确代码示例

根据你的需求(确保操作后数据库未出现特定新记录),分两种场景给出实现:

场景1:确保15秒内持续无目标记录(最长等待19秒完成校验)

如果需要验证操作完成后,接下来的15秒内始终不会出现目标记录,使用during配合noneMatch:

messages = new String[] {"message1", "message2"};
List<String> targetMessages = Arrays.asList(messages);
await("wait for no target records to persist")
        .during(Duration.ofSeconds(15))
        .atMost(Duration.ofSeconds(19))
        .pollInterval(Duration.ofSeconds(1))
        .until(() -> databaseService.getJournalRecords().stream()
                .noneMatch(record -> targetMessages.contains(record.getMessage()))
        );
  • 逻辑说明:Awaitility会先等待条件变为真(无目标记录),然后开始计时15秒,确保这段时间内条件持续成立;如果中途条件失效(出现目标记录),会重新等待条件变为真并重新计时,最长等待19秒完成整个校验流程。

场景2:等待最多19秒,确认无目标记录

如果仅需确认操作完成后,经过足够长时间(19秒)仍无目标记录,无需持续校验,直接去掉during:

messages = new String[] {"message1", "message2"};
List<String> targetMessages = Arrays.asList(messages);
await("wait for no target records")
        .atMost(Duration.ofSeconds(19))
        .pollInterval(Duration.ofSeconds(1))
        .until(() -> databaseService.getJournalRecords().stream()
                .noneMatch(record -> targetMessages.contains(record.getMessage()))
        );
  • 逻辑说明:只要在19秒内条件变为真(无目标记录),就会立即通过;如果19秒后条件仍为假(存在目标记录),则抛出超时异常。

关键优化点

  • 使用noneMatch直接判断“无匹配记录”,语义清晰,避免findFirst().orElse()的冗余操作。
  • 根据实际需求选择是否使用during:需要持续校验用during,仅需最终状态校验则去掉。

内容的提问来源于stack exchange,提问作者Aleksey Bakharev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 04:15:51