In this tutorial, I am going to build an automation framework to test Springboot application with Rest Assured only.
What is Rest Assured?
REST Assured is a Java DSL for simplifying the testing of REST-based services built on top of HTTP Builder. It supports POST, GET, PUT, DELETE, OPTIONS, PATCH, and HEAD requests and can be used to validate and verify the response to these requests.
The rest-Assured library also provides the ability to validate the HTTP Responses received from the server. For e.g. we can verify the Status code, Status message, Headers, and even the Body of the response. This makes Rest-Assured a very flexible library that can be used for testing.
This framework consists of:
- Springboot – 2.5.2
- Java 11
- JUnit – 4.12
- Maven – 3.8.1
- RestAssured – 4.3.3
Steps to setup Cucumber Test Automation Framework for API Testing using Rest-Assured
- Add SpringbootTest and Rest-Assured dependencies to the project
- Create a test file under src/test/java and write the test code
- Run the tests from JUnit
- Run the tests from Command Line
Below is the sample SpringBoot application used for the testing.
The Spring Boot Application class is generated with Spring Initializer. This class acts as the launching point for the application.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootRestServiceApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootRestServiceApplication.class, args);
}
}
The JPA Entity is any Java POJO, which can represent the underlying table structure. As our service is based on the Student table, we will create a Student Entity object.
@Entity
public class Student {
@Id
@GeneratedValue
private Long id;
@NotNull
@Size(min = 4, message = "Name should have atleast 4 characters")
private String name;
@NotBlank(message = "passportNumber is mandatory")
private String passportNumber;
public Student() {
super();
}
public Student(Long id, String name, String passportNumber) {
super();
this.id = id;
this.name = name;
this.passportNumber = passportNumber;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassportNumber() {
return passportNumber;
}
public void setPassportNumber(String passportNumber) {
this.passportNumber = passportNumber;
}
The Repository represents the DAO layer, which typically does all the database operations. Thanks to Spring Data, who provides the implementations for these methods. Let’s have a look at our StudentRepository, which extends the JpaRepository. There are no method declarations here in the StudentRepository. That is because Spring Data’s JpaRepository has already declared basic CRUD methods.
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface StudentRepository extends JpaRepository<Student, Long>{
}
Spring Rest Controller exposes all services on the student resource. RestController used for the below example is shown below.
@RestController
public class StudentController {
@Autowired
private StudentRepository studentRepository;
@GetMapping("/students")
public List<Student> retrieveAllStudents() {
return studentRepository.findAll();
}
@GetMapping("/students/{id}")
public EntityModel<Student> retrieveStudent(@PathVariable long id) {
Optional<Student> student = studentRepository.findById(id);
if (!student.isPresent())
throw new StudentNotFoundException("id-" + id);
EntityModel<Student> resource = EntityModel.of(student.get());
WebMvcLinkBuilder linkTo = linkTo(methodOn(this.getClass()).retrieveAllStudents());
resource.add(linkTo.withRel("all-students"));
return resource;
}
@DeleteMapping("/students/{id}")
public void deleteStudent(@PathVariable long id) {
studentRepository.deleteById(id);
}
@PostMapping("/students")
public ResponseEntity<Object> createStudent(@Valid @RequestBody Student student) {
Student savedStudent = studentRepository.save(student);
URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
.buildAndExpand(savedStudent.getId()).toUri();
return ResponseEntity.created(location).build();
}
@PutMapping("/students/{id}")
public ResponseEntity<Object> updateStudent(@Valid @RequestBody Student student, @PathVariable long id) {
Optional<Student> studentOptional = studentRepository.findById(id);
if (!studentOptional.isPresent())
return ResponseEntity.notFound().build();
student.setId(id);
studentRepository.save(student);
return ResponseEntity.noContent().build();
}
Implementation Steps
Step 1 – Add SpringbootTest and Rest-Assured dependencies to the project
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.rest-assured/rest-assured -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>4.3.3</version>
<scope>test</scope>
</dependency>
Step 2 – Create a test file under src/test/java and write the test code
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SpringbootDemoTests {
private final static String BASE_URI = "http://localhost";
@LocalServerPort
private int port;
private ValidatableResponse validatableResponse;
private ValidatableResponse validatableResponse1;
@Before
public void configureRestAssured() {
RestAssured.baseURI = BASE_URI;
RestAssured.port = port;
}
/* Get operation - Get the details of a Student */
@Test
public void listUsers() {
validatableResponse = given()
.contentType(ContentType.JSON)
.when()
.get("/students")
.then()
.assertThat().statusCode(200);
}
/* Get operation - Get the details of a Student */
@Test
public void listAUser() {
validatableResponse = given()
.contentType(ContentType.JSON)
.when()
.get("/students/10003")
.then()
.assertThat().log().all().statusCode(200)
.body("id",equalTo(10003))
.body("name",equalTo("David"))
.body("passportNumber",equalTo("C1232268"));;
}
/* Create operation - Create a new Student */
@Test
public void createAUser() throws JSONException {
JSONObject newStudent = new JSONObject();
newStudent.put("name", "Timmy");
newStudent.put("passportNumber", "ZZZ12345");
validatableResponse = given()
.contentType(ContentType.JSON).body(newStudent.toString())
.when()
.post("/students")
.then()
.log().all().assertThat().statusCode(201);
/* Verify that a new Student is created */
validatableResponse1 = given()
.contentType(ContentType.JSON)
.when()
.get("/students/1")
.then()
.log().all().assertThat().statusCode(200)
.body("id",equalTo(1))
.body("name",equalTo("Timmy"))
.body("passportNumber",equalTo("ZZZ12345"));
}
/* Update operation - Update PassportNumber of a Student */
@Test
public void updateAUser() throws JSONException {
JSONObject newStudent = new JSONObject();
newStudent.put("name", "John");
newStudent.put("passportNumber", "YYYY1234");
validatableResponse = given()
.contentType(ContentType.JSON).body(newStudent.toString())
.when()
.put("/students/10002")
.then()
.log().all().assertThat().statusCode(204);
/* Verify that the updated Student has updated PassportNumber */
validatableResponse1 = given()
.contentType(ContentType.JSON)
.when()
.get("/students/10002")
.then()
.log().all().assertThat().statusCode(200)
.body("id",equalTo(10002))
.body("name",equalTo("John"))
.body("passportNumber",equalTo("YYYY1234"));
}
/* Delete operation - Delete a Student */
@Test
public void deleteAUser() throws JSONException {
validatableResponse = given()
.contentType(ContentType.JSON)
.when()
.delete("/students/10003")
.then()
.log().all().assertThat().statusCode(200);
/* Verify that the deleted Student Request returns STATUS 404 */
validatableResponse1 = given()
.contentType(ContentType.JSON)
.when()
.get("/students/10003")
.then()
.log().all().assertThat().statusCode(404);
}
}
When a class is annotated with @RunWith or extends a class annotated with @RunWith, JUnit will invoke the class it references to run the tests in that class instead of the runner built into JUnit.
SpringRunner is an alias for the SpringJUnit4ClassRunner. Here, we have simply annotated a JUnit 4-based test class with @RunWith(SpringRunner.class). The Spring TestContext Framework provides generic, annotation-driven unit and integration testing support that is agnostic of the testing framework in use (JUnit, TestNG).
We build the test class with @SpringBootTest annotation which starts up an Application Context used throughout our test. In the classes property of @SpringBootTest annotation, we can specify which configuration classes build our Application Context. By default, @SpringBootTest annotation does not provide any web environment.
In order to set up a test web server we need to use @SpringBootTest’s webEnvironment annotation.
There are a few modes in which the web server can be started.
- RANDOM_PORT – this is a recommended option where a real, embedded web server starts on a random port
- DEFINED_PORT – web server will start on an 8080 or a port defined in application.properties
- MOCK – loads a mock web environment where embedded servers are not started up.
Step 3 – Run the tests from JUnit
Right-click Run as JUnit Tests (Eclipse)
Right Click and select Run SpringBootDemoTests (IntelliJ)

Step 4 – Run the tests from Command Line
Open a command prompt and use the below command to run the tests.
mvn clean verify
We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!