测试Spring REST API。如何在JUnit测试中使用子对象保存实体?

姆伯里

我有两节课:课程和课程。课程是与课程的@OneToMany关系。使用Spring Boot,我创建了一个简单的REST API来管理类。我已经用邮递员手动测试了API,看起来一切正常。

接下来,我编写了简单的JUnite来自动测试API。测试完成后,“课程”实体已正确保存在数据库中,但“课程”抛出错误:

2014-10-15 20:19:15.162错误5812 --- [nio-8080-exec-2] sdrwAbstractRepositoryRestController:无法读取JSON:模板不能为null或为空!(通过参考链:com.mbury.elearning.domain.Lesson [“ course”]);嵌套的异常是com.fasterxml.jackson.databind.JsonMappingException:模板不能为null或为空!(通过参考链:com.mbury.elearning.domain.Lesson [“ course”])

看起来@OneToMany关系没有正确映射,但我不知道该如何处理。有谁知道如何使用包含子对象的实体配置Spring REST以使其正常工作?

波纹管我已经附上了我所有的代码:

LessonTest.java

package com.mbury.elearning;

import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.util.MatcherAssertionErrors.assertThat;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.client.RestTemplate;

import com.mbury.elearning.domain.Course;
import com.mbury.elearning.domain.Lesson;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@IntegrationTest
public class LessonTest {

    final String BASE_URL_COURSE = "http://localhost:8080/courses/";
    final String BASE_URL_LESSON = "http://localhost:8080/lessons/";

    @Test
    public void shouldCreateNewLesson() {

        final String COURSE_TITLE = "test";
        final String COURSE_DESCRIPTION = "test";
        final String LESSON_TOPIC = "test";

        Course course = new Course();
        course.setTitle(COURSE_TITLE);
        course.setDescription(COURSE_DESCRIPTION);

        Lesson lesson = new Lesson();
        lesson.setTopic(LESSON_TOPIC);
        lesson.setCourse(course);
        RestTemplate rest = new TestRestTemplate();

        ResponseEntity<Course> response = rest.postForEntity(BASE_URL_COURSE, course,
                Course.class);
        assertThat(response.getStatusCode(), equalTo(HttpStatus.CREATED));


        ResponseEntity<Lesson> response1 = rest.postForEntity(BASE_URL_LESSON, lesson,
                Lesson.class);
        assertThat(response1.getStatusCode(), equalTo(HttpStatus.CREATED));
    }

}

Course.java

package com.mbury.elearning.domain;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "course")
public class Course  {

    @Column(name = "description")
    private String description;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Integer id;

    @OneToMany(mappedBy = "course")
    private List<Lesson> lesson;

    @Column(name = "title")
    private String title;

    public String getDescription() {
        return description;
    }

    public Integer getId() {
        return id;
    }

    public List<Lesson> getLesson() {
        return lesson;
    }

    public String getTitle() {
        return title;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public void setLesson(List<Lesson> lesson) {
        this.lesson = lesson;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

Lesson.java

package com.mbury.elearning.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "lesson")
public class Lesson {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private int id;

    @Column(name = "topic")
    private String topic;

    @ManyToOne(optional = false)
    @JoinColumn(name = "ID_COURSE")
    Course course;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTopic() {
        return topic;
    }

    public void setTopic(String topic) {
        this.topic = topic;
    }

    public Course getCourse() {
        return course;
    }

    public void setCourse(Course course) {
        this.course = course;
    }
}

CourseRepository.java

package com.mbury.elearning.repository;

import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

import com.mbury.elearning.domain.Course;

@RepositoryRestResource
public interface CourseRepository extends CrudRepository<Course, Integer> {

}

LessonRepository .java

package com.mbury.elearning.repository;

import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

import com.mbury.elearning.domain.Lesson;

@RepositoryRestResource
public interface LessonRepository extends CrudRepository<Lesson, Integer> {

}

应用程序.java

package com.mbury.elearning;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;

@Configuration
@ComponentScan
@EnableJpaRepositories
@Import(RepositoryRestMvcConfiguration.class)
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
安迪·威尔金森

问题的根源在于,您试图重用您的域对象,LessonCourse尝试创建要发送到REST API的JSON有效负载。这不能用作REST API的视图,Lesson或者Course与实现的基于JPA的视图不同。例如,在服务器上,Lessonor的IDCourse是int,而在REST API中,ID是URI。

由于CourseLession都是相当简单的类型,它可能比较容易,当你发送到REST API的请求使用地图。例如,您可以创建如下课程:

Map<String, Object> course = new HashMap<String, Object>();
course.put("title", "test");
course.put("description", "test");

我在上面提到,在REST API中,URI用于标识课程。这意味着在创建课程时,您需要课程所属的课程的URI。您从Location创建课程时返回的响应标头中获得该URI

ResponseEntity<Void> courseResponse = rest.postForEntity(BASE_URL_COURSE, course, Void.class);
assertThat(courseResponse.getStatusCode(), equalTo(HttpStatus.CREATED));
URI courseLocation = courseResponse.getHeaders().getLocation();

然后,您可以使用此URI创建课程地图,并进行API调用以创建它:

Map<String, Object> lesson = new HashMap<String, Object>();
lesson.put("topic", "test");
lesson.put("course", courseLocation);

ResponseEntity<Void> lessonResponse = rest.postForEntity(BASE_URL_LESSON, lesson, Void.class);
assertThat(lessonResponse.getStatusCode(), equalTo(HttpStatus.CREATED));

将所有这些放在一起可以得到以下测试方法:

@Test
public void shouldCreateNewLesson() {
    Map<String, Object> course = new HashMap<String, Object>();
    course.put("title", "test");
    course.put("description", "test");

    RestTemplate rest = new TestRestTemplate();

    ResponseEntity<Void> courseResponse = rest.postForEntity(BASE_URL_COURSE, course, Void.class);
    assertThat(courseResponse.getStatusCode(), equalTo(HttpStatus.CREATED));
    URI courseLocation = courseResponse.getHeaders().getLocation();

    Map<String, Object> lesson = new HashMap<String, Object>();
    lesson.put("topic", "test");
    lesson.put("course", courseLocation);

    ResponseEntity<Void> lessonResponse = rest.postForEntity(BASE_URL_LESSON, lesson, Void.class);
    assertThat(lessonResponse.getStatusCode(), equalTo(HttpStatus.CREATED));
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何使用 JUnit 测试 Spring REST 使用者

来自分类Dev

Spring Data Rest:使用 CURL 测试 deleteByName

来自分类Dev

测试Spring MVC REST控制器

来自分类Dev

无法测试使用Spring Boot开发的REST API

来自分类Dev

使用嵌入式Jetty测试Spring-Rest服务

来自分类Dev

编写“干净”的集成测试-使用jersey 2和Spring的REST

来自分类Dev

使用嵌入式Jetty测试Spring-Rest服务

来自分类Dev

如何在Symfony 2中使用Behat和Mink测试REST API

来自分类Dev

如何在测试 REST API 时使用令牌认证

来自分类Dev

测试API REST SCALA

来自分类Dev

DRY Rest API测试

来自分类Dev

Spring Boot REST应用程序测试方法

来自分类Dev

Spring Rest Controller测试中的NullPointer异常-Java

来自分类Dev

Spring Rest Controller测试中的NullPointer异常-Java

来自分类Dev

Spring Boot REST API单元测试执行中的Null Page对象

来自分类Dev

使用 Kotlin 和 JUnit 5 测试 rest api

来自分类Dev

如何在Spring MVC REST测试中重定向模拟重定向请求?

来自分类Dev

REST Assured:如何在正文中测试“Set”类型的对象?

来自分类Dev

在JMeter中使用参数测试rest api方法

来自分类Dev

超级测试,测试安全的REST API

来自分类Dev

Python Django REST API测试

来自分类Dev

REST API的测试驱动开发

来自分类Dev

JMeter 测试 java rest Api

来自分类Dev

Rest API 的单元测试

来自分类Dev

如何在JUnit测试中使用属性?

来自分类Dev

如何在JUnit测试中使用Mockito?

来自分类Dev

如何在JUnit测试中使用属性?

来自分类Dev

django rest框架测试如何运行测试

来自分类Dev

如何从 MongoDB 检索数据并在 Rest Assured 测试中使用