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

Spock数据驱动测试:首个用例后临时目录相关路径为空致失败

Spock数据驱动测试中第二个用例临时目录相关路径为空的问题

问题原因

核心问题出在AsyncTestUtils的实现逻辑:

  • 当前的awaitUntil和andThen方法接收的是Boolean类型参数,这个参数会在方法调用时立即计算出固定结果,后续PollingConditions每次轮询都只会检查这个静态布尔值,不会重新执行条件判断逻辑。
  • 第一个用例执行时,service刚完成文件写入,tempDir此时非空,!isEmpty(tempDir)直接计算为true,轮询直接通过;后续检查dataSavedDir时,可能刚好文件已经移动完成,!isEmpty(dataSavedDir)也为true,所以用例正常通过。
  • 第二个用例执行时,初始状态下dataSavedDir还未创建,!isEmpty(dataSavedDir)立即计算为false,后续轮询一直检查这个固定的false值,最终超时失败,表现为dataSavedDir为空。
  • 无论是用@TempDir还是手动创建临时目录,只要AsyncTestUtils的逻辑不变,问题都会存在,临时目录配置本身不是直接原因。

解决方案

修改AsyncTestUtils,让它接收Groovy闭包作为条件,这样每次轮询时都会重新执行闭包获取最新的目录状态:

trait AsyncTestUtils<T extends AsyncTestUtils<T>> {
    PollingConditions pollingConditions = new PollingConditions()

    T awaitUntil(Closure<Boolean> condition, String failMessage = "Assertion failed in awaitUntil") {
        pollingConditions.within(10) {
            assert condition.call() : failMessage
        }
        return (T) this
    }

    T andThen(Closure<Boolean> condition, String failMessage = "Assertion failed in andThen") {
        pollingConditions.within(10) {
            assert condition.call() : failMessage
        }
        return (T) this
    }
}

然后在测试代码中,传递闭包而非直接计算布尔值:

then:
Path dataSavedDir = dataDir.resolve("simulations/${simulationId}/${directoryName}")
awaitUntil({ !isEmpty(tempDir) }, "File exists in a tempDir")
        .andThen({ !isEmpty(dataSavedDir) }, "File exists in an appropriate directory of a simulation")
        .andThen({ isEmpty(tempDir) }, "tempDir is empty")

额外注意点

  • 确保isEmpty()方法实现正确,能处理目录不存在的情况(此时应返回true)。
  • 由于simulationId是@Shared的,多个用例会共用同一个ID,需确认被测的StorageService支持同一ID下创建不同子目录(如plots、geometry)的逻辑无冲突。

内容的提问来源于stack exchange,提问作者rafal.sz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 21:13:16