AssertJ软断言调用fail()为何立即终止?如何手动触发软断言错误?
问题描述
使用AssertJ的SoftAssertions编写测试时,遍历列表并在assertSoftly中调用fail()方法,预期输出三条错误信息,但实际第一个错误就导致程序终止。实际场景是:当预期为空的列表非空时,需要为每个元素生成动态错误提示。
代码示例
package com.example; import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; import java.util.List; public class SoftAssertionsTest { @Test void testSoftAssertions() { List.of(1, 2, 3).forEach(element -> SoftAssertions.assertSoftly(softAssertions -> softAssertions.fail("Ka-boom! Index: " + element))); } }
预期输出
Ka-boom! Index: 1 Ka-boom! Index: 2 Ka-boom! Index: 3
实际输出
org.assertj.core.error.AssertJMultipleFailuresError: Multiple Failures (1 failure) -- failure 1 --Ka-boom! Index: 1 at SoftAssertionsTest.lambda$testSoftAssertions$0(SoftAssertionsTest.java:13) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) at by.afinny.credit.unit.repository.SoftAssertionsTest.lambda$testSoftAssertions$1(SoftAssertionsTest.java:12) at java.base/java.lang.Iterable.forEach(Iterable.java:75)
问题原因
你当前的写法是在每次遍历循环中都创建了一个新的SoftAssertions实例。SoftAssertions.assertSoftly()方法的逻辑是:执行传入的断言逻辑后,会立即检查该实例中收集的所有错误,一旦有错误就抛出AssertJMultipleFailuresError终止程序。所以第一次循环时,新的SoftAssertions实例收集到第一个错误后就触发了异常,后续循环根本没机会执行。
解决方法
要实现收集所有错误再统一抛出,需要复用同一个SoftAssertions实例,不要在循环内每次调用assertSoftly()。正确写法有两种:
方式一:手动创建SoftAssertions实例
@Test void testSoftAssertions() { SoftAssertions softAssertions = new SoftAssertions(); List.of(1, 2, 3).forEach(element -> softAssertions.fail("Ka-boom! Index: " + element)); // 最后统一触发所有错误的检查 softAssertions.assertAll(); }
方式二:使用assertSoftly包裹整个循环
把整个遍历逻辑放在assertSoftly()的lambda中,这样只会创建一个SoftAssertions实例,收集所有错误后再统一抛出:
@Test void testSoftAssertions() { SoftAssertions.assertSoftly(softAssertions -> List.of(1, 2, 3).forEach(element -> softAssertions.fail("Ka-boom! Index: " + element))); }
手动触发软断言错误的方法
AssertJ中手动触发软断言错误有两种常用方式:
- 直接调用
softAssertions.fail(String message):就是你代码里用的方式,会把自定义错误信息加入软断言的错误集合。 - 使用
softAssertions.assertThat(xxx).fail(String message):结合断言语法触发错误,比如softAssertions.assertThat(element).fail("元素非法: " + element)。
内容的提问来源于stack exchange,提问作者Sergey Zolotarev
相关产品推荐
相关产品推荐

