Spring Boot测试中使用REST Assured(转)

Posted 奋斗终生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot测试中使用REST Assured(转)相关的知识,希望对你有一定的参考价值。

 

原文:https://rieckpil.de/testing-spring-boot-applications-with-rest-assured/

REST Assured is a Java DSL (Domain Specific Langauge) that aims to simplify testing REST APIs. It follows a BDD (Behavior Driven Development) approach and is influenced by testing APIs with dynamic languages like Groovy. We can use REST Assured to test the REST API of any Java project as it is framework independent. However, REST Assured comes with a great Spring integration for testing our @RestController endpoints that we\'re about to explore with this article.

Spring Boot and REST Assured Project Setup

For our demo application we use Java 11, Spring Boot 2.4.0, and the following dependencies:

As Spring Boot manages the dependency version of REST Assured and all its modules, we can define the spring-mock-mvc without an explicit version. We can override the managed version consistently with the rest-assured.version property.

If we mix up our dependency versions for REST Assured and try to outsmart Spring Boot, we might see several exceptions during test runtime:

As REST Assured has quite some transitive dependencies (Groovy related dependencies, Apache HttpClient, Hamcrest, and Tagsoup), we should favor the manged version from our Spring Boot release.

As I\'ve seen several integration issues for REST Assured and Java 11 projects, consider the following tips:

  • IntelliJ IDEA can help to identify duplicated dependency includes for a Maven project. We can open a visual dependency graph with the following steps: right-click inside our pom.xml -> Maven -> Show Dependencies. A red arrow indicates a violation for dependency convergence. The Maven Enforcer plugin can even detect this as part of your build.
  • REST Assured also provides a rest-assured-all dependency, that can help to solve split package problems.
  • When using Spring Boot together with REST Assured, you might also stumble over exceptions for Groovy related parts of this testing library. Explicitly overriding Spring Boot\'s default Groovy version with groovy.version inside the pom.xml seems to help here.

The Spring MVC RestController Under Test

Our sample application is a book store that exposes the following REST API endpoints to manage its inventory:

The actual implementation of the BookService doesn\'t matter for this demonstration and we can assume it stores our book entities somewhere (e.g. database or in-memory).

For a more realistic example, we\'ll secure the HTTP POST endpoint and only allow authenticated users that have the ADMIN role to access it:

 
Mockito & JUnit Cheat Sheet

JUnit 5 & Mockito Cheat Sheet

Answering 24 questions for the two most essential Java testing libraries.

 

REST Assured Powered MockMvc Test

There are multiple ways to configure REST Assured for a Spring MVC test case. We can manually pass a list of controller objects, provide a MockMvcBuilder , pass a WebApplicationContext or a MockMvc instance.

As we can inject an already initialized MockMvc bean to our test when using Spring Boot\'s test slice annotation @WebMvcTest, we\'ll use it for our REST Assured configuration.

All upcoming requests for this test class will target this MockMvc instance unless we override it explicitly.

With this setup in place, we can write our first test that ensures unauthenticated clients can request our book store\'s inventory:

Due to REST Assured\'s fluent API, one should easily grasp the test setup above. REST Assured also follows a BDD style and  .given().when().then() gives each request a standardized schema.

For writing expectations for our HTTP response body/status/header, we then use Matchers from Hamcrest.

The test above doesn\'t use static imports because there is a small pitfall. When importing the .given() method from REST Assured, we have to make sure it\'s not the traditional non-Spring variant:

Furthermore, there is a potential second pitfall when using a static import and Mockito in the same test.

For tests where we don\'t need a .given() step (e.g., we don\'t pass any query parameter/path variable/header), we can omit it and start our request specification with .when() :