Spring Boot - Testing JSON Serialization and Deserialization With @JsonTest - Example

In this section, we will learn how to test JSON Serialization and Deserialization With @JsonTest in Spring Boot application.

1. @JsonTest

Instead of bootstrapping the entire application context for every test, @JsonTest initializes the Spring application context with only those beans needed to test JSON serialization and deserialization.
@JsonTest annotation can be used to test slices of our application and the auto-configuration that it import by default are listed below:
  • org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
  • org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration
  • org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration
  • org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration
  • org.springframework.boot.test.autoconfigure.json.JsonTestersAutoConfiguration

Testing JSON Serialization and Deserialization Example

2. Creating a spring boot application

First, open the Spring initializr https://start.spring.io

Then, Provide the Group and Artifact name. We have provided Group name com.knf.dev.demo and Artifact json-example. Here I selected the Maven project - language Java 17 - Spring Boot 3.1.5, and Spring Web.


Then, click on the Generate button. When we click on the Generate button, it starts packing the project in a .zip(jsontest-example) file and downloads the project. Then, Extract the Zip file. 

Then, import the project on your favourite IDE.

Final Project Directory:


Complete pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<
modelVersion>4.0.0</modelVersion>
<
parent>
<
groupId>org.springframework.boot</groupId>
<
artifactId>spring-boot-starter-parent</artifactId>
<
version>3.1.5</version>
<
relativePath/> <!-- lookup parent from repository -->
</parent>
<
groupId>com.knf.dev.demo</groupId>
<
artifactId>jsontest-example</artifactId>
<
version>0.0.1-SNAPSHOT</version>
<
name>jsontest-example</name>
<
description>Demo project for Spring Boot</description>
<
properties>
<
java.version>17</java.version>
</
properties>
<
dependencies>
<
dependency>
<
groupId>org.springframework.boot</groupId>
<
artifactId>spring-boot-starter-web</artifactId>
</
dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

</
dependencies>

<
build>
<
plugins>
<
plugin>
<
groupId>org.springframework.boot</groupId>
<
artifactId>spring-boot-maven-plugin</artifactId>
<
configuration>
<
image>
<
builder>paketobuildpacks/builder-jammy-base:latest</builder>
</
image>
</
configuration>
</
plugin>
</
plugins>
</
build>

</
project>

spring-boot-starter-test starter will provide following libraries:

  • JUnit 
  • Spring Test & Spring Boot Test 
  • AssertJ
  • Hamcrest 
  • Mockito 
  • JSONassert 
  • JsonPath 


Create UserDTO

package com.knf.dev.demo.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDate;
import java.util.Map;

public class UserDTO {

private String name;
private String email;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private LocalDate dob;
private Map<String, String> roles;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public LocalDate getDob() {
return dob;
}

public void setDob(LocalDate dob) {
this.dob = dob;
}

public Map<String, String> getRoles() {
return roles;
}

public void setRoles(Map<String, String> roles) {
this.roles = roles;
}
}

Create user.json inside resource directory

{
"name":"Sibin",
"email":"sibin@gmail.com",
"dob":"1970-01-09",
"roles":{
"role1":"Admin",
"role2":"Editor"
}
}
We are using this JSON data for our testing purposes later.

JsontestExampleApplication.java

package com.knf.dev.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class JsontestExampleApplication {

public static void main(String[] args) {
SpringApplication.run(JsontestExampleApplication.class, args);
}

}

Write Unit test for JSON Serialization and Deserialization

Let’s write our test cases by creating UserDTOTests class

Create UserDTOTests

When using JUnit 4, this annotation should be used in combination with @RunWith(SpringRunner.class). But for this example  we are using JUnit 5, there’s no need to add the equivalent @ExtendWith(SpringExtension.class).
package com.knf.dev.demo;

import com.knf.dev.demo.dto.UserDTO;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.test.json.JacksonTester;
import org.springframework.boot.test.json.JsonContent;
import org.springframework.boot.test.json.ObjectContent;
import org.springframework.core.io.Resource;
import org.springframework.util.StreamUtils;

import java.nio.charset.Charset;
import java.time.LocalDate;
import java.time.Month;
import java.util.HashMap;
import java.util.Map;

import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;

@JsonTest
public class UserDTOTests {


@Autowired
private JacksonTester<UserDTO> jacksonTester;

@Value("classpath:user.json")
Resource userResource;

@Test
void serializeInCorrectFormat() throws Exception {

UserDTO userDTO = new UserDTO();
userDTO.setEmail("sibin@gmail.com");
userDTO.setName("Sibin");

LocalDate dob = LocalDate.of(1970, Month.JANUARY, 9);
userDTO.setDob(dob);

Map<String,String> roles= new HashMap<>();
roles.put("role1","Admin");
roles.put("role2","Editor");
userDTO.setRoles(roles);

JsonContent<UserDTO> json = jacksonTester.write(userDTO);

// Assert against a `user.json` file
assertThat(json).isEqualToJson(userResource);

// JSON path based assertions
assertThat(json).hasJsonPathStringValue("@.email");
assertThat(json).extractingJsonPathStringValue("@.dob")
.isEqualTo("1970-01-09");
assertThat(json).extractingJsonPathStringValue("@.name")
.isEqualTo("Sibin");
assertThat(json).extractingJsonPathMapValue("@.roles").
hasFieldOrProperty("role1");
assertThat(json).extractingJsonPathMapValue("@.roles").
extractingByKey("role1").isEqualTo("Admin");
}

@Test
void deserializeFromCorrectFormat() throws Exception {

//Convert Resource to String
String json = StreamUtils.copyToString(userResource.getInputStream(),
Charset.defaultCharset());

UserDTO userDTO = jacksonTester.parseObject(json);

assertThat(userDTO.getEmail()).isEqualTo("sibin@gmail.com");
assertThat(userDTO.getName()).isEqualTo("Sibin");
assertThat(userDTO.getDob()).isEqualTo("1970-01-09");
assertThat(userDTO.getRoles().size()).isEqualTo(2);
}
}
  • JacksonTester is a AssertJ based JSON tester backed by Jackson. If you are using Gson or Jsonb, you have to use its sibling GsonTester or JsonbTester.
  • Here JsonContent is created from a JSON tester. jacksonTester.write(userDTO) returns JsonContent.
  • assertThat is used to check the specified value matches the expected value. It will accept the two parameters, the first contains the actual value, and the second will have the object matching the condition.
  • hasJsonPathStringValue() method is used to check that the actual value at the given JSON path produces a non-null string result.
  • extractingJsonPathStringValue() is used to extract the string value at the given JSON path.
  • extractingJsonPathMapValue() method is used extract the map value at the given JSON path.
  • extractingByKey() method is used to extract the value of given key from the map under test.
  • parseObject() is used to return the object created from parsing the specific JSON String.

3. Run the test


Or you can run the test using following command:

mvn  test -Dtest=UserDTOTests

Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete