Cucumber+SoftAssertions报错:AssertJMultipleFailuresError存在重复JSON字段heading
问题分析
AssertJ的AssertJMultipleFailuresError继承自org.opentest4j.MultipleFailuresError,两者都定义了同名的heading字段。当测试中使用SoftAssertions触发多断言失败时,ExtentReports的JsonFormatter会用Gson序列化该异常,Gson默认的反射序列化会识别到重复字段,直接抛出IllegalArgumentException。
解决方法
方法1:关闭ExtentReports的Json报告生成
如果不需要JSON格式的测试报告,仅保留HTML报告,可在项目根目录的extent.properties中添加以下配置:
extent.reporter.json.start=false
此配置会跳过JsonFormatter的初始化,从根源避免Gson序列化异常问题。
方法2:自定义Gson适配器处理重复字段
若必须保留JSON报告,可通过自定义Gson的TypeAdapter处理AssertJMultipleFailuresError的序列化,忽略重复的heading字段:
- 创建TypeAdapter工厂类,专门处理该异常:
import com.google.gson.Gson; import com.google.gson.TypeAdapter; import com.google.gson.TypeAdapterFactory; import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; import org.assertj.core.error.AssertJMultipleFailuresError; import java.io.IOException; public class AssertJErrorAdapterFactory implements TypeAdapterFactory { @SuppressWarnings("unchecked") @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { if (!AssertJMultipleFailuresError.class.isAssignableFrom(type.getRawType())) { return null; } return (TypeAdapter<T>) new TypeAdapter<AssertJMultipleFailuresError>() { @Override public void write(JsonWriter out, AssertJMultipleFailuresError error) throws IOException { out.beginObject(); // 只序列化子类的heading字段和失败列表 out.name("heading").value(error.getHeading()); out.name("failures").jsonValue(gson.toJson(error.getFailures())); out.endObject(); } @Override public AssertJMultipleFailuresError read(JsonReader in) throws IOException { return null; // 不需要反序列化,留空即可 } }; } }
- 创建工具类替换ExtentReports的Gson实例:
import com.aventstack.extentreports.reporter.JsonFormatter; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.lang.reflect.Field; import java.util.List; public class ExtentGsonFixer { public static void fix() { try { Field gsonField = JsonFormatter.class.getDeclaredField("gson"); gsonField.setAccessible(true); Gson customGson = new GsonBuilder() .registerTypeAdapterFactory(new AssertJErrorAdapterFactory()) .create(); // 获取所有JsonFormatter实例并替换Gson List<JsonFormatter> jsonReporters = com.aventstack.extentreports.service.ExtentService.getReporters().stream() .filter(r -> r instanceof JsonFormatter) .map(r -> (JsonFormatter) r) .toList(); for (JsonFormatter formatter : jsonReporters) { gsonField.set(formatter, customGson); } } catch (Exception e) { e.printStackTrace(); } } }
- 在Cucumber的全局前置Hook中调用修复方法:
import io.cucumber.java.BeforeAll; public class TestSetupHook { @BeforeAll public static void setupExtentReport() { ExtentGsonFixer.fix(); } }
方法3:升级AssertJ版本
升级AssertJ到3.24.0及以上,该版本中AssertJMultipleFailuresError已修改为不再重复定义heading字段,直接使用父类字段,从根本上解决字段冲突问题。
若使用Spring Boot,可在pom.xml中显式指定AssertJ版本:
<properties> <assertj.version>3.24.2</assertj.version> </properties> <dependencies> <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <version>${assertj.version}</version> <scope>test</scope> </dependency> </dependencies>
内容的提问来源于stack exchange,提问作者Francislainy Campos
相关产品推荐
相关产品推荐

