如何对 Flux 输出进行与顺序无关的断言?
How to make order-independent assertions on Flux output?
我有一个test case for a Flux from Project Reactor大致是这样的:
testMultipleChunks(StepVerifier.FirstStep<Chunk> verifier, Chunk chunk1, Chunk chunk2) {
verifier.then(() -> {
worker.add(chunk1);
worker.add(chunk2);
worker.update();
})
.expectNext(chunk1, chunk2)
.verifyTimeout(Duration.ofSeconds(5));
}
事实是,我的工作人员被鼓励并行化工作,这意味着输出的顺序是未定义的。 chunk2, chunk1
同样有效。
如何以与顺序无关的方式对输出进行断言?
我关心的属性:
- 预期集合中的每个元素都存在
- 没有意外元素
- 没有额外的(重复的)事件
我试过这个:
testMultipleChunks(StepVerifier.FirstStep<Chunk> verifier, Chunk chunk1, Chunk chunk2) {
Set<Chunk> expectedOutput = Set.of(chunk1, chunk2);
verifier.then(() -> {
worker.add(chunk1);
worker.add(chunk2);
worker.update();
})
.recordWith(HashSet::new)
.expectNextCount(expectedOutput.size())
.expectRecordedMatches(expectedOutput::equals)
.verifyTimeout(Duration.ofSeconds(5));
}
虽然我认为这做出了我想要的断言,但它在可读性方面出现了可怕的下降。一个清晰的一行、一种方法的断言被 四 行和大量额外的标点符号所取代。
expectedRecordedMatches
在失败时也非常没有信息,只说“预期的集合谓词匹配”而没有提供任何关于期望是什么或结果有多接近的信息。
写这个测试的更清晰的方法是什么?
StepVerifier
不太适合它,因为它会在每个信号发出时验证它,并根据设计实现异步信号的预期顺序。
这特别棘手,因为(看起来)您的测试发布商没有明确完成。
如果它在 N 个元素之后完成(N 是此处的预期数量),我会将传递给 StepVerifier.create
的发布者从 flux
更改为 flux.collectList()
。这样,您将获得 onNext
的 List
视图,并且您可以根据需要声明列表(例如,使用我推荐的 AssertJ)。
最近版本的 Reactor 中的一个替代方案是 TestSubscriber
,它可用于驱动 request
和 cancel()
而无需对阻塞或何时执行断言有任何特别的意见.相反,它在内部存储它看到的事件(onNext
进入 List
,onComplete
和 onError
存储为终端 Signal
...)和您可以访问这些以进行任意断言。
我有一个test case for a Flux from Project Reactor大致是这样的:
testMultipleChunks(StepVerifier.FirstStep<Chunk> verifier, Chunk chunk1, Chunk chunk2) {
verifier.then(() -> {
worker.add(chunk1);
worker.add(chunk2);
worker.update();
})
.expectNext(chunk1, chunk2)
.verifyTimeout(Duration.ofSeconds(5));
}
事实是,我的工作人员被鼓励并行化工作,这意味着输出的顺序是未定义的。 chunk2, chunk1
同样有效。
如何以与顺序无关的方式对输出进行断言?
我关心的属性:
- 预期集合中的每个元素都存在
- 没有意外元素
- 没有额外的(重复的)事件
我试过这个:
testMultipleChunks(StepVerifier.FirstStep<Chunk> verifier, Chunk chunk1, Chunk chunk2) {
Set<Chunk> expectedOutput = Set.of(chunk1, chunk2);
verifier.then(() -> {
worker.add(chunk1);
worker.add(chunk2);
worker.update();
})
.recordWith(HashSet::new)
.expectNextCount(expectedOutput.size())
.expectRecordedMatches(expectedOutput::equals)
.verifyTimeout(Duration.ofSeconds(5));
}
虽然我认为这做出了我想要的断言,但它在可读性方面出现了可怕的下降。一个清晰的一行、一种方法的断言被 四 行和大量额外的标点符号所取代。
expectedRecordedMatches
在失败时也非常没有信息,只说“预期的集合谓词匹配”而没有提供任何关于期望是什么或结果有多接近的信息。
写这个测试的更清晰的方法是什么?
StepVerifier
不太适合它,因为它会在每个信号发出时验证它,并根据设计实现异步信号的预期顺序。
这特别棘手,因为(看起来)您的测试发布商没有明确完成。
如果它在 N 个元素之后完成(N 是此处的预期数量),我会将传递给 StepVerifier.create
的发布者从 flux
更改为 flux.collectList()
。这样,您将获得 onNext
的 List
视图,并且您可以根据需要声明列表(例如,使用我推荐的 AssertJ)。
最近版本的 Reactor 中的一个替代方案是 TestSubscriber
,它可用于驱动 request
和 cancel()
而无需对阻塞或何时执行断言有任何特别的意见.相反,它在内部存储它看到的事件(onNext
进入 List
,onComplete
和 onError
存储为终端 Signal
...)和您可以访问这些以进行任意断言。