Spring Boot 2.2 & RestAssured: MissingMethodException

I recently updated an application from Spring Boot v2.1 to v2.2. I didn’t expect it to be easy and especially due to update of Kotlin, I also had to change some code.

Nevertheless I had some strange error concerning tests that costs me some time. After simply updating Spring Boot and fixing compile errors, I executed the tests and got the following runtime error:

groovy/lang/GroovyObject
 java.lang.NoClassDefFoundError: groovy/lang/GroovyObject
     at java.base/java.lang.ClassLoader.defineClass1(Native Method)
     […]
     at io.restassured.RestAssured.(RestAssured.java:346)
     at RestAssuredTest.init(RestAssuredTest.kt:11)
     […]
 Caused by: java.lang.ClassNotFoundException: groovy.lang.GroovyObject
     at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
     at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
     at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
     … 58 more

Well, this one was the easy part: Simply adding a dependency to org.codehaus.groovy:groovy solved this error. Nevertheless I didn’t expect such an error to ocurr after a “simple” update of Spring Boot.

Now for the hard part. After adding the dependency, an even more strange exception got thrown:

groovy.lang.MissingMethodException: No signature of method: io.restassured.internal.ContentParser.parse() is applicable for argument types: (io.restassured.internal.RestAssuredResponseImpl, io.restassured.internal.ResponseParserRegistrar...) values: [io.restassured.internal.RestAssuredResponseImpl@4ee4c86b, io.restassured.internal.ResponseParserRegistrar@22029a56, ...]
Possible solutions: wait(), any(), grep()
 at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:70)
 at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:49)
 at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
 at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:151)
 at io.restassured.internal.ResponseSpecificationImpl$HamcrestAssertionClosure.validate(ResponseSpecificationImpl.groovy:478)
 at io.restassured.internal.ResponseSpecificationImpl$HamcrestAssertionClosure$validate$1.call(Unknown Source)
 […]

This one costs me a lot of time. I first thought of some dependency incompatibility, e.g. Spring dependency management pulls in a library in version X but my code / another library expects the library in version Y – but this wasn’t the case. I also had a look into the source code, but that simply told me, that the call to the parse() method seemed to be correct. Even debugging and stepping through the code didn’t gave me any hint.

As I didn’t had any more ideas, I built up a completly new project without Spring and just with the necessary dependencies to run a simple RestAssured test, that would trigger the error:

class RestAssuredTest {
    
    @Before
    fun init() {
        RestAssured.port = 8080
        RestAssured.baseURI = "http://localhost"
    }

    @Test
    fun triggerTheError() {
        RestAssured
            .given()
            .`when`()
            .contentType("application/json")
            .get("/v2/api-docs")
            .then()
            .statusCode(200)
            .body("swagger", `is`("2.0"))
    }

}

After that I started to add more dependencies and Spring dependency management until I got into the same error. As the root cause for the error must have something to do with the dependencies, I executed ./gradlew dependencies and compared it to the simple setup without Spring. It still took me some time, but then I found the problem: Spring dependency management removes the transitive dependency to org.codehaus.groovy:groovy-xml of RestAssured. Manually adding this dependency solved the error.

Besides that, I don’t understand why this missing dependency causes such a strange error with a message that doesn’t contain any hint to the root cause. And additionally I don’t understand why Spring dependency management removes this transitive dependency…

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.