我正在使用 Spock 测试一些涉及将数据保存到磁盘的代码(Spring 应用程序)。我需要测试多个案例,因此我使用
where:
关键字来计划多个测试案例。测试的代码将一些数据保存到 tempDir
中,然后将其移动到 dataDir
中。
不知何故,无论我如何尝试配置临时目录,无论是通过
@TempDir
还是Files.createTempDirectory()
,第一个测试都很好通过,而第二个测试失败,因为临时Path
为空。如果我注释掉任何一个案例,另一个案例就会通过。
可能需要注意的是,tempDir 看起来不错,但由于
dataSavedDir
为空,测试总是失败。
我的测试规格:
class SimulationStorageSpec extends Specification implements StorageDtos, AsyncTestUtils {
SimulationStorageService service
@TempDir Path tempDir
@TempDir Path dataDir
@Shared String simulationId = "ABC123"
def setup() {
service = new SimulationStorageConfiguration().simulationDataStorageService(tempDir.toString(), dataDir.toString())
}
def "should accept raw simulation data file and save it"() {
when:
service.processAttachment(datafile, dto)
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")
and:
try (InputStream is = Files.newInputStream(dataSavedDir.toFile().listFiles()[0].toPath())) {
assert DigestUtils.sha256Hex(is) == dto.getFileHash()
}
where:
datafile | dto | directoryName
singleRawPlotData() | singleRawPlotDto(simulationId) | "plots"
singleRawGeometryData() | singleRawGeometryDto(simulationId) | "geometry"
}
AsyncTestUtils(只是链 PollingConditions 的一个特征,测试的代码是异步的):
trait AsyncTestUtils <T extends AsyncTestUtils<T>> {
PollingConditions pollingConditions = new PollingConditions()
T awaitUntil(Boolean condition, String failMessage = "Assertion failed in awaitUntil") {
pollingConditions.within(10) {
assert condition : failMessage
}
return (T) this
}
T andThen(Boolean condition, String failMessage = "Assertion failed in andThen") {
pollingConditions.within(10) {
assert condition : failMessage
}
return (T) this
}
}
这可能是临时目录配置、我的异步测试代码或其他问题吗?
特征中的函数接受布尔值:
T awaitUntil(Boolean condition, String failMessage = "Assertion failed in awaitUntil") {
pollingConditions.within(10) {
assert condition : failMessage
}
return (T) this
}
它们被称为:
awaitUntil(!isEmpty(tempDir), "File exists in a tempDir")
。所以这只是传递一个布尔结果; “断言”
在调用awaitUntil
之前完成。
所以结果已经是注定的;等待这个 结果/断言是无用的。它要么总是立即起作用,要么永远不起作用。
所以你想要的是传递一个“布尔供应商”。和 groovy 最方便的方法是传递一个闭包:
// call passing the thing to check
awaitUntil({!isEmpty(tempDir)}, "File exists in a tempDir")
// accept a function and call it in the `assert`
T awaitUntil(Closure<Boolean> conditionFn, String failMessage = "Assertion failed in awaitUntil") {
pollingConditions.within(10) {
assert conditionFn() : failMessage
}
return (T) this
}