You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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字段:

  1. 创建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; // 不需要反序列化,留空即可
            }
        };
    }
}
  1. 创建工具类替换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();
        }
    }
}
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 22:57:02