【发布时间】:2018-02-13 19:21:34
【问题描述】:
AssertJ(或 JUnit)是否有办法在单个(流畅的)表达式中链接同一被测单元上的多个断言,其中一个断言可能会抛出异常。本质上,我试图断言:
如果被测单元 (X) 没有导致特定异常,则它 可能,然后断言被测单元上的特定属性不成立。否则断言异常属于某种类型。
例如,有没有办法表达以下错误代码可能EITHER导致异常或出现strings.size() != 10000:
@Test/*(expected=ArrayIndexOutOfBoundsException.class)*/
public void raceConditions() throws Exception {
List<String> strings = new ArrayList<>(); //not thread-safe
Stream.iterate("+", s -> s+"+")
.parallel()
.limit(10000)
//.peek(e -> System.out.println(e+" is processed by "+ Thread.currentThread().getName()))
.forEach(e -> strings.add(e));
System.out.println("# of elems: "+strings.size());
}
AssertJ 有一个soft assertions 的概念,是在这样的场景中使用的吗?如果是这样,我会很感激一些代码示例。
或者也许有更好的框架专门为这种类型的场景设计?
谢谢。
【问题讨论】:
-
我认为这里同时发生了两件事。您正在尝试强制竞争条件,并且您正在尝试测试仅在发生异常时才发生的事情,而这可能不会发生。单元测试应该是确定性的。如果您正在编写非确定性测试,那么您不是在编写单元测试,而是在编写其他内容。检查竞争条件很重要,但通常这是压力测试或模糊测试,而不是单元测试。单元测试应该产生一致的、可预测的结果。压力测试会产生统计数据。
-
这可能是一个选择吗?
if(yourConditionIsNotMet) {Assert.fail(SomeCustomException)},这个SomeCustomException表示比赛 -
@tadman 从某种意义上说,它们是确定性的,我期望在这两种情况下都会出现一致且可预测的失败。开放是一种失败。有什么东西可以断言存在竞争条件吗?
-
我认为您不应该测试竞争条件。您应该测试您的操作在正常条件下是否按预期执行。如果这是一个问题,二级压力测试框架可以摆脱竞争条件。这就是你可以滥用系统到故障点的地方,这样你就可以理解你的代码可能爆炸的所有方式。其中一些故障可能是错误,其中一些错误可能需要单元测试来验证它们已得到修复。
-
这没有任何意义。非确定性意味着非确定性。无法保证此代码表现出这两种行为中的任何一种。结果列表的
size()方法完全有可能返回10000,这并不意味着列表处于有效、一致的状态。它可能包含错误排序的元素、虚假的nulls 和重复项,甚至是比报告大小短的数组。但即使有一个完全正确的列表结果也是可能的结果之一。可能是代码永远不会完成。这是不确定的。
标签: unit-testing junit java-8 race-condition assertj