JUnit – Testing REST APIs
In this tutorial, you will learn how to use JUnit to test REST APIs.
REST APIs are a critical component of modern web applications, and testing them ensures that endpoints behave as expected, handle edge cases gracefully, and provide reliable data.
In this tutorial, you will learn how to set up, configure, and execute REST API tests using JUnit, along with best practices for efficient API testing.
Why Test REST APIs?
- Ensure Correctness: Validate that endpoints return the expected data and status codes.
- Handle Edge Cases: Verify how APIs behave with invalid inputs, missing parameters, or unexpected conditions.
- Maintain Stability: Catch regressions when modifying API implementations.
- Enhance Security: Test for vulnerabilities such as injection attacks or unauthorized access.
Setting Up the Environment
Before testing REST APIs, ensure you have the necessary dependencies and configurations. For example, if you’re using Spring Boot, include the following dependencies in your pom.xml
:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
These dependencies include tools like RestTemplate
, MockMvc, and RestAssured for API testing.
Basic Example: Using RestTemplate
The RestTemplate
class in Spring simplifies making HTTP requests. Let’s test a sample REST endpoint that returns user details:
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
class RestTemplateTest {
@Test
void testGetUser() {
RestTemplate restTemplate = new RestTemplate();
String url = "https://jsonplaceholder.typicode.com/users/1";
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
assertEquals(200, response.getStatusCodeValue(), "Expected HTTP status 200");
System.out.println(response.getBody());
}
}
Explanation:
- HTTP GET Request: The
getForEntity()
method sends a GET request to the specified URL. - Response Validation: The status code and body are validated to ensure the API response is correct.
Advanced Example: Using RestAssured
RestAssured is a popular library for testing REST APIs. It provides a fluent interface for making requests and validating responses:
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
import org.junit.jupiter.api.Test;
class RestAssuredTest {
@Test
void testGetUser() {
given()
.baseUri("https://jsonplaceholder.typicode.com")
.when()
.get("/users/1")
.then()
.statusCode(200)
.body("name", equalTo("Leanne Graham"))
.body("address.city", equalTo("Gwenborough"));
}
}
Explanation:
- Fluent Interface: The
given()
,when()
, andthen()
methods make the code readable and expressive. - JSON Path Validation: The
body()
method checks specific fields in the JSON response.
Mocking APIs with MockMvc
If you’re testing a Spring Boot application, MockMvc
is an excellent tool for testing controllers without starting the entire application:
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
@SpringBootTest
@AutoConfigureMockMvc
class MockMvcTest {
@Autowired
private MockMvc mockMvc;
@Test
void testGetUser() throws Exception {
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("John Doe"))
.andExpect(jsonPath("$.email").value("john.doe@example.com"));
}
}
Key Points:
- Integration Testing:
MockMvc
tests your controllers in isolation without starting a server. - JSON Path Validation: Validates specific fields in the JSON response.
Testing POST Requests
Let’s test an endpoint that creates a new resource using a POST request:
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
import org.junit.jupiter.api.Test;
class RestAssuredPostTest {
@Test
void testCreateUser() {
given()
.baseUri("https://jsonplaceholder.typicode.com")
.contentType("application/json")
.body("{ \"name\": \"John Doe\", \"email\": \"john.doe@example.com\" }")
.when()
.post("/users")
.then()
.statusCode(201)
.body("name", equalTo("John Doe"))
.body("email", equalTo("john.doe@example.com"));
}
}
Here, the given()
method specifies the request payload, and post()
sends the POST request.
Best Practices for REST API Testing
- Test All Scenarios: Validate positive cases, negative cases, and edge cases for each endpoint.
- Automate Assertions: Use libraries like RestAssured or JSON Path for expressive and automated validation.
- Mock External APIs: For isolated tests, mock external APIs to avoid dependencies on real services.
- Check Status Codes: Validate HTTP status codes to ensure proper communication.
- Run Tests Regularly: Integrate API tests into CI/CD pipelines to catch issues early.
Conclusion
JUnit provides a versatile framework for testing REST APIs. With tools like RestTemplate
, RestAssured, and MockMvc, you can validate endpoints efficiently and ensure their reliability. By following the examples and best practices outlined in this guide, you can create robust and maintainable API tests, ensuring the quality of your web services.