使用 REST Assured 进行测试时出现 java.lang.AbstractMethodError

Posted

技术标签:

【中文标题】使用 REST Assured 进行测试时出现 java.lang.AbstractMethodError【英文标题】:Getting java.lang.AbstractMethodError when I test using REST Assured 【发布时间】:2020-07-16 02:43:48 【问题描述】:

我正在尝试使用 REST Assured v4.3.0 测试在我的控制器类中定义的 REST api,但是在运行测试时我得到了 java.lang.AbstractMethodError。我知道这个错误正在发生,因为我正在调用一个抽象方法,但我很难解决它。

似乎由于SampleControllerTest.java 中的.body(is(equalTo("success"))) 而发生错误,因为当我删除此行时,测试成功。我尝试了一些方法来解决它,但没有成功:

在线搜索建议和示例,但它们要么是旧版本,要么与io.rest-assured/spring-mock-mvc无关 尝试了不同的匹配器(org.hamcrest.Matchers.*org.hamcrest.CoreMatchers.*) 尝试在 pom 文件中显式添加 org.hamcrest/hamcrest 依赖项

这是我的代码供您参考:

代码结构:

test
|- src/
|  |- main/
|  |  |- java/
|  |  |  |- org/
|  |  |  |  |- example/
|  |  |  |  |  |- Application.java
|  |  |  |  |  |- SampleController.java
|  |- test/
|  |  |- java/
|  |  |  |- org/
|  |  |  |  |- example/
|  |  |  |  |  |- SampleControllerTest.java
|- target/
|- pom.xml

Application.java

package org.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application 
    public static void main(String[] args) 
        SpringApplication.run(Application.class, args);
    

SampleController.java

package org.example;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SampleController 
    @RequestMapping(value = "/sample")
    @ResponseStatus(value = HttpStatus.OK)
    public String getSample() 
        return "success";
    

SampleControllerTest.java

package org.example;

import org.junit.Test;

import static io.restassured.module.mockmvc.RestAssuredMockMvc.*;
import static org.hamcrest.Matchers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

public class SampleControllerTest 
    @Test
    public void testGetSample() 
        given()
            .standaloneSetup(new SampleController())
            .when()
            .get("/sample")
            .then()
            .assertThat(status().isOk())
            .body(is(equalTo("success")));
    

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>org.example</groupId>
    <artifactId>test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>8</java.version>
        <start-class>org.example.Application</start-class>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- JUnit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.rest-assured/spring-mock-mvc -->
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>spring-mock-mvc</artifactId>
            <version>4.3.0</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.rest-assured/json-path -->
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>json-path</artifactId>
            <version>4.3.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.rest-assured/xml-path -->
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>xml-path</artifactId>
            <version>4.3.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured -->
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>4.3.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

当我使用mvn test 运行测试时,这是我得到的错误:

[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.325 s <<< FAILURE! - in org.example.SampleControllerTest
[ERROR] testGetSample(org.example.SampleControllerTest)  Time elapsed: 1.288 s  <<< ERROR!
java.lang.AbstractMethodError: Method io/restassured/internal/ResponseSpecificationImpl.getProperty(Ljava/lang/String;)Ljava/lang/Object; is abstract
        at org.example.SampleControllerTest.testGetSample(SampleControllerTest.java:20)

提前感谢您的帮助!

【问题讨论】:

【参考方案1】:

由于放心4.3.0将Groovy从2.5.7升级到3.0.2,见rest-assured/changelog.txt at master · rest-assured/rest-assured,可以在pom文件中指定groovy版本。

  <properties>
    <rest-assured.version>4.3.0</rest-assured.version>
    <groovy.version>3.0.2</groovy.version>
  </properties>

【讨论】:

对于 Gradle,应该是 ext["groovy.version"] = "3.0.3" (Groovy DSL) 或 extra.apply set("groovy.version", "3.0.3") (Kotlin DSL)。【参考方案2】:

这看起来像是 REST Assured 4.3.0 中的一个错误,您的代码适用于 4.2.0 版本。

我没有找到打开的问题。 https://github.com/rest-assured/rest-assured/issues

【讨论】:

这可能是真的。当我删除 io.rest-assured/rest-assured 依赖并保留 io.rest-assured/spring-mock-mvc 时,它工作正常。 Ops...我做你做的事,也能工作!我从 "io.rest-assured/rest-assured" 更改为 io.rest-assured/spring-mock-mvc 并添加 pom.xml xml &lt;io-rest-assured.version&gt;4.3.0&lt;/io-rest-assured.version&gt; &lt;dependency&gt; &lt;groupId&gt;io.rest-assured&lt;/groupId&gt; &lt;artifactId&gt;spring-mock-mvc&lt;/artifactId&gt; &lt;version&gt;$io-rest-assured.version&lt;/version&gt; &lt;scope&gt;test&lt;/scope&gt; &lt;/dependency&gt; 不,这不是 REST Assured 中的错误,而是依赖项解析中的错误。有些东西(在这种情况下是 Spring)依赖于 Groovy 2.1.3(对于所有工件)。 REST Assured 依赖于 Groovy 3.0.2(或 3.0.3),但仅声明***依赖项,而不是 org.codehaus.groovy:groovy 本身 - Spring 胜出。【参考方案3】:

我使用 4.2.0 而不是 4.3.0 .. 它对我有用

【讨论】:

我使用@jörg-pfründer 评论上面的分辨率,它适用于我在 build.gradle 中放入的 4.3.1 版本:groovy configurations.all resolutionStrategy.cacheDynamicVersionsFor 10, "minutes" resolutionStrategy.eachDependency DependencyResolveDetails details -&gt; if (details.requested.group == 'org.codehaus.groovy') details.useVersion "3.0.2" details.because "needed by rest-assured&gt;=4.3" 【参考方案4】:

对于 Maven 项目,以下代码适用于 Spring Boot 项目:

<properties>
       <groovy.version>3.0.7</groovy.version>
       <rest-assured.version>4.3.3</rest-assured.version>
   </properties>

   <dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-test</artifactId>
           <scope>test</scope>
       </dependency>
       <dependency>
           <groupId>io.rest-assured</groupId>
           <artifactId>spring-mock-mvc</artifactId>
           <scope>test</scope>
           <exclusions>
               <exclusion>
                   <artifactId>groovy</artifactId>
                   <groupId>org.codehaus.groovy</groupId>
               </exclusion>
           </exclusions>
       </dependency>
       <dependency>
           <groupId>org.codehaus.groovy</groupId>
           <artifactId>groovy</artifactId>
           <version>$groovy.version</version>
       </dependency>
       <dependency>
           <groupId>org.codehaus.groovy</groupId>
           <artifactId>groovy-xml</artifactId>
           <version>$groovy.version</version>
       </dependency>
       <dependency>
           <groupId>org.codehaus.groovy</groupId>
           <artifactId>groovy-json</artifactId>
           <version>$groovy.version</version>
       </dependency>
       <dependency>
           <groupId>io.rest-assured</groupId>
           <artifactId>json-path</artifactId>
           <version>$rest-assured.version</version>
           <scope>test</scope>
       </dependency>
       <dependency>
           <groupId>io.rest-assured</groupId>
           <artifactId>xml-path</artifactId>
           <version>$rest-assured.version</version>
           <scope>test</scope>
       </dependency>
   </dependencies>
```

【讨论】:

【参考方案5】:

我也有一个java.lang.AbstractMethodError,但使用了另一种方法。

rest-assured 4.3 升级了它的实现以使用groovy 3,见rest assured's release notes

在我的例子中,依赖解析将 groovy 降级为使用一些 2.x 版本。

如果你使用 maven:

您可以使用mvn dependency:tree 进行检查。 如果存在冲突,请将必要的 groovy 依赖项作为版本=>3.0.2 的直接依赖项添加到您的项目中。

如果你使用 gradle:

您可以使用gradle depencencies 进行检查。 如果存在冲突,则添加解决策略:

configurations.all 
    resolutionStrategy.eachDependency  DependencyResolveDetails details ->
        if (details.requested.group == 'org.codehaus.groovy') 
            details.useVersion "3.0.2"
            details.because "needed by rest-assured>=4.3"
        
    

也许这可以帮助某人。

【讨论】:

或者,也许更短或更易读:constraints iplementation("org.codehaus.groovy:groovy:3.0.3") because("Needed by REST Assured") 【参考方案6】:

如果您使用 Rest Assured 版本 4.3.2,只需明确将 groovy 版本指定为 3.0.6 即可修复错误。

<rest-assured.version>4.3.2</rest-assured.version>
<groovy.version>3.0.6</groovy.version>

祝你好运。

【讨论】:

【参考方案7】:

原来io.rest-assured/spring-mock-mvc 依赖与io.rest-assured/rest-assured 依赖冲突。一旦我从pom.xml 中删除了io.rest-assured/rest-assured,测试就成功了。

几年前,当我使用 REST Assured 版本 3.1.1 时,我可以保留这两个依赖项,但也许新版本不允许这样做。

【讨论】:

【参考方案8】:

在 pom.xml 中使用下面的放心依赖

    <dependency>
        <groupId>io.rest-assured</groupId>
        <artifactId>rest-assured</artifactId>
        <version>4.2.0</version>
        <scope>test</scope>
    </dependency>

【讨论】:

以上是关于使用 REST Assured 进行测试时出现 java.lang.AbstractMethodError的主要内容,如果未能解决你的问题,请参考以下文章

Rest-Assured表单身份验证不起作用

如何将JSON响应转换为Java List-使用Rest Assured进行API测试

rest-assured : Restful API 测试利器 - 真正的黑盒单元测试(跟Spring-Boot更配哦)

接口测试 rest-assured 使用指南

接口测试框架REST Assured测试get接口

Rest Assured 不使用自定义 ObjectMapper