``我正在try 学习Spring Boot,并试图从我的API端点发送一个课程对象列表. 但在检索课程对象列表的测试用例中,我收到以下错误:

org.springframework.web.client.RestClientException: Error while extracting response for type [java.util.List[com.socgen.jpa.hibernate.learnjpa.entity.Course]] and content type [application/json]

我收到此错误的测试用例 在postman 中,我收到了课程对象的列表. 我正在使用以下data.sql文件填充数据库

insert into course(id, name) values(99, 'DBMS');

Schema.sql 如果存在课程,则丢弃表格;

create table course (
        id bigint not null,
        name varchar(255) UNIQUE,
        primary key (id)
    );
@Test
    void shouldReturnAListOfAllCourses() {
        // List<Course> result = courseRepository.findAllCoursesInTable();
        // assertThat(result.size()).isEqualTo(2);
        ResponseEntity<List<Course>> getResponse = restTemplate.exchange(
                "/all",
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<Course>>() {
                });

        assertThat(getResponse.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(getResponse.getBody()).isNotNull();
        assertThat(getResponse.getBody().size()).isEqualTo(2); // Adjust the expected size as needed
    }

所有其他测试用例只通过了我提到的失败的测试用例.

测试用例文件

package com.jpa.hibernate.learnjpa;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;

import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.socgen.jpa.hibernate.learnjpa.entity.Course;
import com.socgen.jpa.hibernate.learnjpa.repository.CourseRepository;

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

import java.net.URI;
import java.util.List;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class LearnjpaApplicationTests {

    @Autowired
    TestRestTemplate restTemplate;
    @Autowired
    private CourseRepository courseRepository;

    @Test
    void ShouldReturnACourseOfGivenId() {
        ResponseEntity<String> response = restTemplate.getForEntity("/course/99", String.class);
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        DocumentContext documentContext = JsonPath.parse(response.getBody());
        Number id = documentContext.read("$.id");
        assertThat(id).isNotNull();
        assertThat(id).isEqualTo(99);
    }

    @Test
    void ShouldReturn404ForNonRegisteredIds() {
        ResponseEntity<String> response = restTemplate.getForEntity("/course/1000", String.class);
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
    }

    @Test
    @DirtiesContext
    void shouldReturnNoContentWhenDelete() {
        ResponseEntity<Void> response = restTemplate.exchange("/course/99", HttpMethod.DELETE, null, Void.class);
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
    }

    @Test
    @DirtiesContext
    void shouldReturnCreated() {
        // creating the new course
        Course course = new Course("CSE");
        ResponseEntity<Void> response = restTemplate.postForEntity("/course/add", course, Void.class);
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED);

        // course was created
        URI locationOfNewCourse = response.getHeaders().getLocation();
        ResponseEntity<String> getResponse = restTemplate.getForEntity(locationOfNewCourse, String.class);
        assertThat(getResponse.getStatusCode()).isEqualTo(HttpStatus.OK);

        // making sure can't create duplicate course
        ResponseEntity<Void> response2 = restTemplate.postForEntity("/course/add", course, Void.class);
        assertThat(response2.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
    }

    @Test
    @DirtiesContext
    void shouldUpdateAndReturnNewCourse() {
        Course updatedCourse = new Course("NETWORKS");
        updatedCourse.setId(99L);
        HttpEntity<Course> requestObject = new HttpEntity<>(updatedCourse);
        ResponseEntity<Course> updateResponse = restTemplate.exchange("/course/update/99", HttpMethod.PUT,
                requestObject, Course.class);
        assertThat(updateResponse.getStatusCode()).isEqualTo(HttpStatus.CREATED);
        assertThat(updateResponse.getBody()).isNotNull();
        assertThat(updateResponse.getBody().getName()).isNotEqualTo("DBMS");
        assertThat(updateResponse.getBody().getName()).isEqualTo("NETWORKS");
    }

    @Test
    void shouldReturnAListOfAllCourses() {
        // List<Course> result = courseRepository.findAllCoursesInTable();
        // assertThat(result.size()).isEqualTo(2);
        ResponseEntity<List<Course>> getResponse = restTemplate.exchange(
                "/all",
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<Course>>() {
                });

        assertThat(getResponse.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(getResponse.getBody()).isNotNull();
        assertThat(getResponse.getBody().size()).isEqualTo(2); // Adjust the expected size as needed
    }

}

课程实体


package com.jpa.hibernate.learnjpa.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

@Entity
@Table(name = "course")
public class Course {
    @Id
    @GeneratedValue
    private Long id;
    
    @Column(unique = true)
    private String name;

    public Course(String name){
        this.name = name;
    }
    
    public Course(){

    }

    // getters and setters
    public Long getId() {
        return id;
    }
    public String getName() {
        return name;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return name + " " + id;
    }
}

课程资源库

package com.jpa.hibernate.learnjpa.repository;


import org.springframework.stereotype.Repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import com.socgen.jpa.hibernate.learnjpa.entity.Course;

import java.util.List;
import java.util.Optional;



@Repository
public interface CourseRepository extends JpaRepository<Course, Long> {
    Optional<Course> findById(Long id);
    void deleteById(Long id); //does nothing if ID not found
    Optional<Course> findByName(String name);

    @Query(value = "select * from course", nativeQuery = true)
    List<Course> findAllCoursesInTable();

    
}

CourseController

package com.jpa.hibernate.learnjpa.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;

import com.socgen.jpa.hibernate.learnjpa.Services.CourseService;
import com.socgen.jpa.hibernate.learnjpa.entity.Course;

import java.net.URI;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.PutMapping;

@RestController
@RequestMapping("/course")
public class CourseController {
    @Autowired
    private CourseService courseService;

    @GetMapping("/{id}")
    public ResponseEntity<Course> getCourseById(@PathVariable Long id) {
        Course course = courseService.findById(id);
        if(course == null){
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(course);
    }

    // getting all the courses 
    @GetMapping("/all")
    public ResponseEntity<List<Course>> getAllCourses() {
        return ResponseEntity.ok().body(courseService.getAllCourses());
    }
    
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteCourseById(@PathVariable Long id){
        if(courseService.deleteById(id)) return ResponseEntity.noContent().build();
        return ResponseEntity.notFound().build();        
    }
    
    @PostMapping("/add")
    public ResponseEntity<Void> addCourse(@RequestBody Course course, UriComponentsBuilder ucb) {
        Course newCourse = courseService.addNewCourse(course);
        if(newCourse != null){
            URI locationOfNewCourse = ucb.path("course/{id}").buildAndExpand(newCourse.getId()).toUri();
            return ResponseEntity.created(locationOfNewCourse).build();
        }
        return ResponseEntity.badRequest().build();   
    }
    @PutMapping("update/{id}")
    public ResponseEntity<Course> putMethodName(@PathVariable String id, @RequestBody Course course, UriComponentsBuilder ucb) {
        Course updatedCourse = courseService.updateCourse(course);
        return ResponseEntity.created(null).body(updatedCourse);
    }
}

课程服务

package com.jpa.hibernate.learnjpa.Services;

import java.util.List;
import com.jpa.hibernate.learnjpa.entity.Course;

public interface CourseService {
    Course findById(Long id);
    Boolean deleteById(Long id); //returns true if any object was deleted else returns false
    Course addNewCourse(Course course);
    Course updateCourse(Course course);
    List<Course> getAllCourses();
} 

课程服务实施

package com.jpa.hibernate.learnjpa.Services;

import java.util.List;
import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.socgen.jpa.hibernate.learnjpa.entity.Course;
import com.socgen.jpa.hibernate.learnjpa.repository.CourseRepository;

@Service
public class CourseServiceImp implements CourseService {
   
    Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    CourseRepository courseRepository;

    @Override
    public Course findById(Long id) {
        Optional<Course> course = courseRepository.findById(id);
        logger.info(course.toString());
        if(course.isPresent()) return course.get();
        return null;
    }

    @Override
    public Boolean deleteById(Long id) {
        Optional<Course> course = courseRepository.findById(id);
        if(!course.isPresent()) return false;
        courseRepository.deleteById(id);
        return true;
    }

    @Override
    public Course addNewCourse(Course course) {
        Optional<Course> courseExists = courseRepository.findByName(course.getName());
        if(courseExists.isPresent()) return null;
        Course newCourse = courseRepository.save(course);
        return newCourse;
    }

    @Override
    public Course updateCourse(Course course) {
        Course updatedCourse = courseRepository.save(course);
        return updatedCourse;
    }

    @Override
    public List<Course> getAllCourses() {
        return courseRepository.findAllCoursesInTable();
    }

}

Pom.xml 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.1</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.socgen.jpa.hibernate</groupId>
    <artifactId>learnjpa</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>learnjpa</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

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

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

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.2.3</version>
            </plugin>

        </plugins>
    </build>

</project>

我不知道我做错了什么,因为当我try 在postman 中测试终结点时,它可以正常工作.这可能是测试用例的问题.

推荐答案

您在以下位置忘记了前缀/course

ResponseEntity<List<Course>> getResponse = restTemplate.exchange("/course/all", /* rest of params */);

哦,当测试控制器时,看看MockMvc.

Java相关问答推荐

try Dockerize Maven应用程序,但发布版本21不支持"

Android视图覆盖不阻止点击它后面的控件

Cucumber TestNG Assert失败,出现java. lang. Numbercycle异常

H2弹簧靴试验跌落台

为什么在枚举中分支预测比函数调用快?

在模拟超类中设置非setter属性的值

将不受支持的时区UT重写为UTC是否节省?

在Spring终结点中,是否可以同时以大写和小写形式指定枚举常量?

在Java 17中使用两个十进制数字分析时间时出错,但在Java 8中成功

由于在生成器模式中使用泛型,lambda表达式中的返回类型错误

Domino中不同的java.Protocol.handler.pkgs设置在XPages Java中导致错误

在java中使用不同的application.properties-jar而不使用Spring

在不使用instanceof或强制转换的情况下从父类变量调用子类方法

在缺少字段时使用Jackson With Options生成Optional.Empty()

如何修复Spring Boot应用程序中的RestDocumentationGenerationException:java.io.FileNotFoundException:/curl-request.adoc(只读文件系统)?

使用原子整数的共享计数器并发增量

java.util.LinkedList()是如何成为MutableList的实例的?

窗口启动后不久,从java.awt.Graphics disapear创建的矩形

从 Java 17 切换回 Java 8 后出现的问题

在java中使用SevenZip.openArchive方法后无法删除文件