There is a recent breaking change to AssertJ which breaks JsonContentAssert.extractingJsonPath*() functions in Spring Boot Test.

For example JsonContentAssert.extractingJsonPathStringValue(CharSequence expression, Object... args) expects to return AbstractCharSequenceAssert<?, String>, but now Assertions.assertThat(String actual) returns StringAssert instead which causes NoSuchMethodError to be thrown.

This problem can be replicated with Spring Boot 2.5.1 and AssertJ 3.20.0 with following example:

Code example
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.test.json.JacksonTester;
import org.springframework.boot.test.json.JsonContent;

import java.io.IOException;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

class SomeClass {

    private final String field;

    SomeClass(String field) {
        this.field = field;
    }

    public String getField() {
        return field;
    }
}

@JsonTest
public class BrokenSerializationTest {

    @Autowired
    private JacksonTester<SomeClass> jacksonTester;

    @Test
    public void valueFromJsonPathCanNotBeExtracted() throws IOException {
        JsonContent<SomeClass> serialized = jacksonTester.write(new SomeClass("I am a string"));

        assertThatThrownBy(() -> assertThat(serialized).extractingJsonPathStringValue("field"))
                .isInstanceOf(NoSuchMethodError.class)
                .hasMessage("'org.assertj.core.api.AbstractStringAssert org.assertj.core.api.Assertions.assertThat(java.lang.String)'");
    }
}

Comment From: wilkinsona

Thanks for letting us know. While the change is binary incompatible it appears to be source compatible so this won't be a problem in Spring Boot 2.6 where we'll upgrade to AssertJ 3.20.x (or later). We could fix the problem in earlier versions by using reflection to call assertThat so that the return type isn't baked into Boot's byte code. Flagging for team attention so we can decide if that extra complexity is worth it.

Comment From: snicoll

I personally don't think this is worth it. IMO, this is one of those cases where an upgrade of Spring Boot is needed to support a newer version of a third party library.

@Urokhtor can you share why you've overridden the assertJ version? (We support 3.19.0).

Comment From: wilkinsona

This branch contains the changes that are necessary to support 3.20 at runtime having compiled against an earlier version.

Comment From: philwebb

The reflection hack doesn't seem too bad to me. Perhaps we can only do it as a fallback when NoSuchMethodError is thrown?

Comment From: Urokhtor

I personally don't think this is worth it. IMO, this is one of those cases where an upgrade of Spring Boot is needed to support a newer version of a third party library.

@Urokhtor can you share why you've overridden the assertJ version? (We support 3.19.0).

We don't use AssertJ only through Spring Boot, so we've defined it explicitly as a dependency. We noticed this problem because we automatically update our dependencies and we noticed couple of tests failing with most recent version of AssertJ.

Comment From: wilkinsona

I've added a second commit to my branch that only uses reflection as a fallback. It's a little more verbose as you'd expect, but it does feel less risky.

Comment From: snicoll

There's a 3.20.2 that reverts some binary incompatible change in the meantime. I wonder if that would fix this issue.

Comment From: wilkinsona

There's still a slight binary incompatibility with 3.20.2 but it only affects our tests. As such, I don't think we need to do anything any more.

@Urokhtor If you'd like to use AssertJ 3.20.x with Spring Boot 2.5.x (or earlier) please use AssertJ 3.20.2.