英文:
Getting java.lang.AbstractMethodError when I test using REST Assured
问题
我正在尝试使用`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`依赖。
以下是您参考的代码:
**代码结构:**
```plaintext
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)
提前感谢您的任何帮助!
<details>
<summary>英文:</summary>
I'm trying to test a REST api defined in my controller class using `REST Assured v4.3.0`, but I get `java.lang.AbstractMethodError` when I run the test. I understand this error is occurring because I'm calling an abstract method, but I'm having a hard time resolving it. 
It seems that the error is occurring due to `.body(is(equalTo("success")))` in `SampleControllerTest.java` because when I remove this line, the test succeeds. I tried a few things to resolve it, but didn't get any success:
- Searched online for suggestions and examples, but they are either for older versions or not related to `io.rest-assured/spring-mock-mvc`
- Tried different matchers (`org.hamcrest.Matchers.*` and `org.hamcrest.CoreMatchers.*`)
- Tried adding `org.hamcrest/hamcrest` dependency in the pom file explicitly
Here's my code for your reference:
**Code structure:**
test
|- src/
|  |- main/
|  |  |- java/
|  |  |  |- org/
|  |  |  |  |- example/
|  |  |  |  |  |- Application.java
|  |  |  |  |  |- SampleController.java
|  |- test/
|  |  |- java/
|  |  |  |- org/
|  |  |  |  |- example/
|  |  |  |  |  |- SampleControllerTest.java
|- target/
|- pom.xml
**Application.java**
```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>
When I run the test using mvn test, this is the error I get:
[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)
Thanks for any help in advance!
答案1
得分: 15
由于升级到rest-assured 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>
英文:
Because of rest-assured 4.3.0 upgrade the Groovy from 2.5.7 to 3.0.2, see rest-assured/changelog.txt at master · rest-assured/rest-assured, you can specified the groovy version in pom file.
  <properties>
    <rest-assured.version>4.3.0</rest-assured.version>
    <groovy.version>3.0.2</groovy.version>
  </properties>
答案2
得分: 9
似乎是REST Assured 4.3.0中的一个bug,您的代码在4.2.0版本中可以工作。
我没有找到已打开的问题。https://github.com/rest-assured/rest-assured/issues
英文:
It looks like a bug in REST Assured 4.3.0, your code works with 4.2.0 version.
I didn't find opened issue. https://github.com/rest-assured/rest-assured/issues
答案3
得分: 6
我使用了4.2.0而不是4.3.0...对我有效。
英文:
I used 4.2.0 instead of 4.3.0 .. it works for me
答案4
得分: 5
对于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>
英文:
For Maven projects, the code below works well with Spring Boot projects:
<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>
```
</details>
# 答案5
**得分**: 4
我还遇到了一个`java.lang.AbstractMethodError`,但是发生在另一个方法上。
rest-assured 4.3 将其实现升级以使用[groovy 3][1],详见[rest assured的发布说明][2]。
在我的情况下,依赖解析将groovy降级为使用某个2.x版本。
如果你使用的是Maven:
你可以使用`mvn dependency:tree`来检查。如果存在冲突,将必要的groovy依赖项作为直接依赖项添加到你的项目中,版本为=>3.0.2。
如果你使用的是Gradle:
你可以使用`gradle dependencies`来检查。如果存在冲突,可以添加一个解析策略:
```groovy
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"
        }
    }
}
```
也许这可以帮助某人。
  [1]: https://groovy-lang.org/releasenotes/groovy-3.0.html
  [2]: https://github.com/rest-assured/rest-assured/blob/master/changelog.txt
<details>
<summary>英文:</summary>
I also had an `java.lang.AbstractMethodError` but on another method.
rest-assured 4.3 upgraded it's implementation to use [groovy 3][1], see [rest assured's release notes][2]
In my case the dependency resolution downgraded groovy to use some 2.x version.
If you use maven:
You can check that using `mvn dependency:tree`. 
If there's a conflict, add the necessary groovy dependencies as direct dependencies with a version=>3.0.2 to your project. 
If you use gradle:
You can check that using `gradle depencencies`.
If there's a conflict, then add a resolution strategy:
    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"
            }
        }
    }
Maybe that can help somebody.
  [1]: https://groovy-lang.org/releasenotes/groovy-3.0.html
  [2]: https://github.com/rest-assured/rest-assured/blob/master/changelog.txt
</details>
# 答案6
**得分**: 2
```xml
使用以下依赖项在 pom.xml 中引入 Rest Assured:
	<dependency>
		<groupId>io.rest-assured</groupId>
		<artifactId>rest-assured</artifactId>
		<version>4.2.0</version>
		<scope>test</scope>
	</dependency>
```
<details>
<summary>英文:</summary>
Use below dependency  of rest assured in pom.xml
		<dependency>
			<groupId>io.rest-assured</groupId>
			<artifactId>rest-assured</artifactId>
			<version>4.2.0</version>
			<scope>test</scope>
		</dependency>
</details>
# 答案7
**得分**: 2
如果您使用的是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>
祝您好运。
<details>
<summary>英文:</summary>
If you use Rest Assured version `4.3.2`, just specify **explictly** the groovy version to `3.0.6` and that fixes the error.
    <rest-assured.version>4.3.2</rest-assured.version>
    <groovy.version>3.0.6</groovy.version>
Good luck.
</details>
# 答案8
**得分**: 1
原来 `io.rest-assured/spring-mock-mvc` 依赖与 `io.rest-assured/rest-assured` 依赖发生了冲突。一旦我从 `pom.xml` 中移除了 `io.rest-assured/rest-assured`,测试就成功运行了。
几年前,当我使用 REST Assured 版本 `3.1.1` 时,我可以同时保留这两个依赖,但可能更新的版本不允许这样做。
<details>
<summary>英文:</summary>
It turns out that `io.rest-assured/spring-mock-mvc` dependency was conflicting with `io.rest-assured/rest-assured` dependency. Once I removed the `io.rest-assured/rest-assured` from `pom.xml`, the test worked successfully. 
A few years ago when I was using REST Assured version `3.1.1`, I could keep both of these dependencies, but perhaps newer versions don't allow this.
</details>
				通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论