DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Migrate, Modernize and Build Java Web Apps on Azure: This live workshop will cover methods to enhance Java application development workflow.

Modern Digital Website Security: Prepare to face any form of malicious web activity and enable your sites to optimally serve your customers.

Kubernetes in the Enterprise: The latest expert insights on scaling, serverless, Kubernetes-powered AI, cluster security, FinOps, and more.

E-Commerce Development Essentials: Considering starting or working on an e-commerce business? Learn how to create a backend that scales.

Related

  • Spring Microservices RESTFul API Documentation With Swagger Part 1
  • Creating Spring Boot and React CRUD Full Stack Application with Maven
  • Microservice Communication Using Consul, Ribbon, and Feign - A Step-by-Step Guide
  • Develop a Spring Boot REST API in AWS: PART 4 (CodePipeline / CI/CD)

Trending

  • A Modern Open-Source Technology That Conquers ACH Batch Processing
  • Ultimate Guide to Smart Agriculture Systems Using IoT
  • Performance of ULID and UUID in Postgres Database
  • Converting Multi-Frame TIFF to GIF in Cross-Platform .NET Environments
  1. DZone
  2. Coding
  3. Frameworks
  4. Test-Driven Development With a Spring Boot REST API

Test-Driven Development With a Spring Boot REST API

While TDD starts with unit tests, it doesn't stop there. Let's look at how integration tests come into play with a Spring Boot-based REST API.

Swathi Prasad user avatar by
Swathi Prasad
·
Sep. 12, 18 · Tutorial
Like (8)
Save
Tweet
Share
60.6K Views

Join the DZone community and get the full member experience.

Join For Free

I deal with integration tests for RESTful applications a lot, however, I had not particularly tried Test Driven Development (TDD) methodologies. Therefore, I decided to give it a try, and I say now tell that I quite like it. I shall assume you already have some basic ideas of TDD, therefore I shall forgo an introduction to TDD.

In this article, let us look at how we can adopt TDD methodology in implementing a Spring Boot RESTful application.

Creating a Spring Boot Application

To start an application with Spring Boot is really easy; we just need to include Spring Boot dependencies in the Maven pom.xml and we need a Java class file.

Create a simple Maven project in the IDE of your choice. I have created mine in Eclipse. The project structure is as follows:

The Maven POM contains the following:

<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>
       <groupId>com.swathisprasad.tdd</groupId>
       <artifactId>tdd-springboot</artifactId>
       <version>1.0.0-SNAPSHOT</version>
       <!—Spring Boot starter parent goes here -->
<properties>
              <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
              <java.version>1.8</java.version>
       </properties>
</project>

Edit the pom.xml and add the following Spring Boot dependencies. Here, we are adding spring-boot-starter-parent as a parent for our project.

<parent>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-parent</artifactId>
              <version>2.0.4.RELEASE</version>
              <relativePath /> <!-- lookup parent from repository -->
  </parent>

Under the dependencies section, add the following dependency.

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

In combination with spring-boot-starter-parent, the spring-boot-starter-web dependency allows us to run the web application.

Here is the class which is responsible for running the application.

package com.swathisprasad.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
 * @author swathi
 *
 */
@SpringBootApplication
public class Application {
                  /**
                   * @param args
                   */
                  public static void main(String[] args) {
                                    SpringApplication.run(Application.class, args);
                  }
}

So far we have created a simple Spring Boot application. We can test our application by running Application.java as a Java application.

As we are focusing on TDD methodologies, let us first create a simple integration test. Edit the pom.xml file and add the following dependencies.

             <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-actuator</artifactId>
              </dependency>
              <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-test</artifactId>
                      <scope>test</scope>
              </dependency>
             <dependency>
                      <groupId>com.jayway.restassured</groupId>
                      <artifactId>rest-assured</artifactId>
                      <version>2.8.0</version>
                     <scope>test</scope>
              </dependency>
              <dependency>
                      <groupId>org.codehaus.groovy</groupId>
                      <artifactId>groovy-all</artifactId>
                      <version>2.4.5</version>
              </dependency>

Here, spring-boot-starter-actuator provides production ready feature such as monitoring our app, gathering metrics and so on. The spring-boot-starter-test allows to bootstrap Spring context before executing tests.

The Maven plugin rest-assured is a Java DSL for testing REST services. This plugin requires groovy-all to run the tests.

We will add maven-failsafe-plugin plugin to execute the integration tests.

<build>
	<plugins>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-failsafe-plugin</artifactId>
			<executions>
				<execution>
					<id>integration-test</id>
					<goals>
						<goal>integration-test</goal>
					</goals>
				</execution>
				<execution>
					<id>verify</id>
					<phase>verify</phase>
					<goals>
						<goal>verify</goal>
					</goals>
				</execution>
			</executions>
		</plugin>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
			<executions>
				<execution>
					<id>pre-integration-test</id>
					<goals>
						<goal>start</goal>
					</goals>
				</execution>
				<execution>
					<id>post-integration-test</id>
					<goals>
						<goal>stop</goal>
					</goals>
				</execution>
			</executions>
		</plugin>
	</plugins>
</build>

Here, we have also added spring-boot-maven-plugin with some execution tasks in order to execute the tests during the deployment process.

Let's create a test which makes a simple GET request and expects data in the response body.

package com.swathisprasad.springboot.controller;
import static com.jayway.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.swathisprasad.springboot.Application;
import com.jayway.restassured.RestAssured;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
/**
 * @author swathi
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(classes = Application.class) 
@TestPropertySource(value={"classpath:application.properties"})
@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
public class SpringRestControllerTest {
    @Value("${server.port}") 
    int port;
       @Test
       public void getDataTest() {
              get("/api/tdd/responseData").then().assertThat().body("data", equalTo("responseData"));
       }
       @Before
       public void setBaseUri () {
               RestAssured.port = port;
               RestAssured.baseURI = "http://localhost"; // replace as appropriate
       }
}

Note that we have added some annotations here to run the tests in a web environment.

@RunWith(SpringJUnit4ClassRunner.class) supports loading of the Spring application context.

@ContextConfiguration defines class-level metadata that is used to determine how to load and configure an ApplicationContext for integration tests.

@TestPropertySource is used to configure the location of properties files.

SpringBootTest tells Spring Boot to go and look for a main configuration class (one with @SpringBootApplication, for instance) and use that to start a Spring application context.

As we have not defined a REST endpoint yet, we can run the above test using the mvn verify command to see the test fail.

Let's fix our test by introducing a REST controller.

package com.swathisprasad.springboot;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
 * @author swathi
 *
 */
@RestController
public class SpringRestController {
                  @RequestMapping(path = "/api/tdd/{data}", method= RequestMethod.GET)
                  public Response getData(@PathVariable("data") String data) {
                                    return new Response(data);
                  }
                  //inner class
                  class Response {
                                    private String data;
                                    public Response(String data) {
                                                      this.data = data;
                                    }
                                    public String getData() {
                                                      return data;
                                    }
                  }
}

In the class above, we have a REST endpoint which accepts "data" as an input and returns a new instance of "Response" in the response body.

Let's run the mvn verify command again. It should now run the tests successfully.

Wrapping Up

Developing our implementation with TDD enables us to define the requirements in the form of tests. This approach also helps to maintain our code to make it easier to read and maintain while still passing the tests.

The complete source code can be found on GitHub.

Spring Framework REST Web Protocols Spring Boot Test-driven development API Testing application

Published at DZone with permission of Swathi Prasad, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Spring Microservices RESTFul API Documentation With Swagger Part 1
  • Creating Spring Boot and React CRUD Full Stack Application with Maven
  • Microservice Communication Using Consul, Ribbon, and Feign - A Step-by-Step Guide
  • Develop a Spring Boot REST API in AWS: PART 4 (CodePipeline / CI/CD)

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: