extent-framework / extentreports-java

Extent Reporting Library, Java
http://extentreports.com
Apache License 2.0
224 stars 127 forks source link

Class org.assertj.core.error.AssertJMultipleFailuresError declares multiple JSON fields named heading - Cucumber + SoftAssertions #424

Open francislainy opened 9 months ago

francislainy commented 9 months ago

We keep getting this error in our cucumber tests.

java.lang.IllegalArgumentException: class org.assertj.core.error.AssertJMultipleFailuresError declares multiple JSON fields named heading

at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:172)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:102)
    at com.google.gson.Gson.getAdapter(Gson.java:489)

    .....

    at com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter.finishReport(ExtentCucumberAdapter.java:300)
    at com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter.access$600(ExtentCucumberAdapter.java:62)
    at com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter$8.receive(ExtentCucumberAdapter.java:136)
    at com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter$8.receive(ExtentCucumberAdapter.java:133)
    at io.cucumber.core.eventbus.AbstractEventPublisher.send(AbstractEventPublisher.java:51)
    at io.cucumber.core.eventbus.AbstractEventBus.send(AbstractEventBus.java:12)
    at io.cucumber.core.runtime.SynchronizedEventBus.send(SynchronizedEventBus.java:47)
    at io.cucumber.core.runtime.CucumberExecutionContext.emitTestRunFinished(CucumberExecutionContext.java:131)
    at io.cucumber.core.runtime.CucumberExecutionContext.finishTestRun(CucumberExecutionContext.java:118)
    at io.cucumber.junit.Cucumber$FinishTestRun.evaluate(Cucumber.java:250)

It seems to be related to Gson and or Assert Core when using SoftAssertions. We don't use Gson directly in our tests, but it comes as a transitive dependency and when trying to exclude it, I would be getting other errors and the tests won't run.

I have these versions and dependencies:

 <properties>
        <java.version>11</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>

        <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
        <maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>

        <spring-boot.version>2.6.6</spring-boot.version>
        <cucumber.version>7.2.3</cucumber.version>

        <extent.report.version>1.3.0</extent.report.version>
        <rally.api.version>1.3</rally.api.version> //Custom dependency

    </properties>

  <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>io.cucumber</groupId>
                <artifactId>cucumber-bom</artifactId>
                <version>${cucumber.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

     <dependencies>

        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-spring</artifactId>
        </dependency>

        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-junit</artifactId>
        </dependency>

        <dependency>
            <groupId>tech.grasshopper</groupId> // Uses Gson
            <artifactId>extentreports-cucumber7-adapter</artifactId>
            <version>${extent.report.version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>

        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.jupiter</groupId>
                    <artifactId>junit-jupiter-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.logging.log4j</groupId>
                    <artifactId>log4j-to-slf4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.mycustom.cs</groupId>
            <artifactId>cs-rally-api</artifactId> // Uses Gson
            <version>${rally.api.version}</version>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents.core5</groupId>
            <artifactId>httpcore5</artifactId>
        </dependency>

    </dependencies>

This is a sample for how we are doing the assertions:

   @Given("I debug test")
    public void iDebug() {
        SoftAssertions softAssertions = new SoftAssertions();
        softAssertions.assertThat(1).isEqualTo(2);
        softAssertions.assertThat(2).isEqualTo(3);
        softAssertions.assertAll();
    }
    }

Tried with the latest versions for Spring Boot, Cucumber and ExtentReports,

 <properties>

        <java.version>17</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>

        <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
        <maven-surefire-plugin.version>3.1.0</maven-surefire-plugin.version>

        <spring-boot.version>3.2.1</spring-boot.version>
        <cucumber.version>7.12.0</cucumber.version>

        <extent-report.version>1.14.0</extent-report.version>
        <rally-api.version>1.3</rally-api.version>
        <jackson-databind-nullable.version>0.2.6</jackson-databind-nullable.version>
    </properties>

but the error still persists:

java.lang.IllegalArgumentException: Class org.assertj.core.error.AssertJMultipleFailuresError declares multiple JSON fields named 'heading'; conflict is caused by fields org.assertj.core.error.AssertJMultipleFailuresError#heading and org.opentest4j.MultipleFailuresError#heading

at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:302)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:130)
    at com.google.gson.Gson.getAdapter(Gson.java:556)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:55)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:196)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:368)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:196)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:368)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:196)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:368)
    at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:1371)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:196)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:368)
    at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:1371)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:196)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:368)
    at com.google.gson.internal.bind.ObjectTypeAdapter.write(ObjectTypeAdapter.java:183)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:70)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61)
    at com.google.gson.Gson.toJson(Gson.java:842)
    at com.google.gson.Gson.toJson(Gson.java:812)
    at com.google.gson.Gson.toJson(Gson.java:783)
    at com.aventstack.extentreports.reporter.JsonFormatter.flush(JsonFormatter.java:57)
    at com.aventstack.extentreports.reporter.JsonFormatter$1.onNext(JsonFormatter.java:37)
    at com.aventstack.extentreports.reporter.JsonFormatter$1.onNext(JsonFormatter.java:30)
    at io.reactivex.rxjava3.subjects.PublishSubject$PublishDisposable.onNext(PublishSubject.java:310)
    at io.reactivex.rxjava3.subjects.PublishSubject.onNext(PublishSubject.java:226)
    at com.aventstack.extentreports.ReactiveSubject.onFlush(ReactiveSubject.java:83)
    at com.aventstack.extentreports.AbstractProcessor.onFlush(AbstractProcessor.java:95)
    at com.aventstack.extentreports.ExtentReports.flush(ExtentReports.java:279)
    at com.aventstack.extentreports.service.ExtentService.flush(ExtentService.java:47)
    at com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter.finishReport(ExtentCucumberAdapter.java:301)
    at com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter$8.receive(ExtentCucumberAdapter.java:137)
    at com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter$8.receive(ExtentCucumberAdapter.java:134)
    at io.cucumber.core.eventbus.AbstractEventPublisher.send(AbstractEventPublisher.java:51)
    at io.cucumber.core.eventbus.AbstractEventBus.send(AbstractEventBus.java:12)
    at io.cucumber.core.runtime.SynchronizedEventBus.send(SynchronizedEventBus.java:47)
    at io.cucumber.core.runtime.CucumberExecutionContext.emitTestRunFinished(CucumberExecutionContext.java:118)
    at io.cucumber.core.runtime.CucumberExecutionContext.finishTestRun(CucumberExecutionContext.java:105)
    at io.cucumber.junit.platform.engine.CucumberEngineExecutionContext.finishTestRun(CucumberEngineExecutionContext.java:126)
    at io.cucumber.junit.platform.engine.CucumberEngineDescriptor.ifChildren(CucumberEngineDescriptor.java:51)
    at io.cucumber.junit.platform.engine.CucumberEngineDescriptor.cleanUp(CucumberEngineDescriptor.java:36)
    at io.cucumber.junit.platform.engine.CucumberEngineDescriptor.cleanUp(CucumberEngineDescriptor.java:11)

Thank you very much.

francislainy commented 9 months ago

The issue has also been raised here https://github.com/grasshopper7/extentreports-cucumber7-adapter/issues/37 and here: https://stackoverflow.com/questions/77856505/class-org-assertj-core-error-assertjmultiplefailureserror-declares-multiple-json

francislainy commented 9 months ago

This fixes the issue: https://github.com/grasshopper7/extentreports-cucumber7-adapter/issues/37#issuecomment-1903551525

Not sure I should close this one, or still worth it investigating a different way to fix it?

Thank you.