From c606fc82f42eb7d3da90e8749a457e5897befdec Mon Sep 17 00:00:00 2001 From: Eugene Kovko <37694937+eukovko@users.noreply.github.com> Date: Mon, 1 Jan 2024 23:00:36 +0100 Subject: [PATCH] Bael 7066 (#15515) * BAEL-7066: Happy path test * BAEL-7066: Fix the test * BAEL-7066: Change assume to assert * BAEL-7066: Ignore Nulls test * BAEL-7066: Combined tests * BAEL-7066: Fix a typo and removed smoke tests * BAEL-7066: Fix formatting * BAEL-7066: Renamed to Employees * BAEL-7066: Extract a base test class * BAEL-7066: Added a skeleton for non absent test * BAEL-7066: Added absent employee tests * BAEL-7066: Fix formatting * BAEL-7066: Empty values test * BAEL-7066: Moved controllers * BAEL-7066: Renamed methods * BAEL-7066: Refactor nonNull tests * BAEL-7066: Refactor nonEmpty tests * BAEL-7066: Refactor nonAbsent tests * BAEL-7066: Renamed the base test * BAEL-7066: cleanup * BAEL-7066: Fixed indents --- .../com/baeldung/jsonignore/Application.java | 8 ++ .../jsonignore/absentfields/Employee.java | 67 ++++++++++ .../jsonignore/absentfields/Salary.java | 30 +++++ .../AbsentEmployeeEchoController.java | 19 +++ .../controller/EmployeeEchoController.java | 19 +++ .../EmptyEmployeeEchoController.java | 19 +++ .../jsonignore/emptyfields/Employee.java | 93 +++++++++++++ .../jsonignore/emptyfields/PhoneNumber.java | 28 ++++ .../jsonignore/emptyfields/Salary.java | 30 +++++ .../jsonignore/nullfields/Employee.java | 83 ++++++++++++ ...oyeeEchoControllerBaseIntegrationTest.java | 123 ++++++++++++++++++ ...eeFieldsEchoControllerIntegrationTest.java | 50 +++++++ ...eeFieldsEchoControllerIntegrationTest.java | 60 +++++++++ ...eeFieldsEchoControllerIntegrationTest.java | 45 +++++++ 14 files changed, 674 insertions(+) create mode 100644 spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/Application.java create mode 100644 spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/absentfields/Employee.java create mode 100644 spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/absentfields/Salary.java create mode 100644 spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/controller/AbsentEmployeeEchoController.java create mode 100644 spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/controller/EmployeeEchoController.java create mode 100644 spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/controller/EmptyEmployeeEchoController.java create mode 100644 spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/emptyfields/Employee.java create mode 100644 spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/emptyfields/PhoneNumber.java create mode 100644 spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/emptyfields/Salary.java create mode 100644 spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/nullfields/Employee.java create mode 100644 spring-boot-modules/spring-boot-data-3/src/test/java/com/baeldung/jsonignore/AbstractEmployeeEchoControllerBaseIntegrationTest.java create mode 100644 spring-boot-modules/spring-boot-data-3/src/test/java/com/baeldung/jsonignore/NonAbsentEmployeeFieldsEchoControllerIntegrationTest.java create mode 100644 spring-boot-modules/spring-boot-data-3/src/test/java/com/baeldung/jsonignore/NonEmptyEmployeeFieldsEchoControllerIntegrationTest.java create mode 100644 spring-boot-modules/spring-boot-data-3/src/test/java/com/baeldung/jsonignore/NonNullEmployeeFieldsEchoControllerIntegrationTest.java diff --git a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/Application.java b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/Application.java new file mode 100644 index 0000000000..3072ca16ac --- /dev/null +++ b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/Application.java @@ -0,0 +1,8 @@ +package com.baeldung.jsonignore; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + +} diff --git a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/absentfields/Employee.java b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/absentfields/Employee.java new file mode 100644 index 0000000000..5dbcd89cc0 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/absentfields/Employee.java @@ -0,0 +1,67 @@ +package com.baeldung.jsonignore.absentfields; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import java.util.Optional; + +@JsonInclude(Include.NON_ABSENT) +public class Employee { + + private String lastName; + private String firstName; + private long id; + private Optional salary; + + + public Employee() { + } + + public Employee(final long id, final String lastName, final String firstName, final Optional salary) { + this.id = id; + this.lastName = lastName; + this.firstName = firstName; + this.salary = salary; + } + + public String getLastName() { + return lastName; + } + + public String getFirstName() { + return firstName; + } + + public long getId() { + return id; + } + + public void setLastName(final String lastName) { + this.lastName = lastName; + } + + public void setFirstName(final String firstName) { + this.firstName = firstName; + } + + public void setId(final long id) { + this.id = id; + } + + public Optional getSalary() { + return salary; + } + + public void setSalary(final Optional salary) { + this.salary = salary; + } + + @Override + public String toString() { + return "Employee{" + + "lastName='" + lastName + '\'' + + ", firstName='" + firstName + '\'' + + ", id=" + id + + ", salary=" + salary + + '}'; + } +} diff --git a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/absentfields/Salary.java b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/absentfields/Salary.java new file mode 100644 index 0000000000..f9bbe1a225 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/absentfields/Salary.java @@ -0,0 +1,30 @@ +package com.baeldung.jsonignore.absentfields; + +import java.math.BigDecimal; + +public class Salary { + + private BigDecimal hourlyRate; + + public Salary() { + } + + public Salary(BigDecimal hourlyRate) { + this.hourlyRate = hourlyRate; + } + + public BigDecimal getHourlyRate() { + return hourlyRate; + } + + public void setHourlyRate(final BigDecimal hourlyRate) { + this.hourlyRate = hourlyRate; + } + + @Override + public String toString() { + return "Salary{" + + "hourlyRate=" + hourlyRate + + '}'; + } +} diff --git a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/controller/AbsentEmployeeEchoController.java b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/controller/AbsentEmployeeEchoController.java new file mode 100644 index 0000000000..d5d442154e --- /dev/null +++ b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/controller/AbsentEmployeeEchoController.java @@ -0,0 +1,19 @@ +package com.baeldung.jsonignore.controller; + +import com.baeldung.jsonignore.absentfields.Employee; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping(AbsentEmployeeEchoController.USERS) +public class AbsentEmployeeEchoController { + + public static final String USERS = "/absent_employees"; + + @PostMapping + public Employee echoUser(@RequestBody Employee employee) { + return employee; + } +} diff --git a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/controller/EmployeeEchoController.java b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/controller/EmployeeEchoController.java new file mode 100644 index 0000000000..258b167265 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/controller/EmployeeEchoController.java @@ -0,0 +1,19 @@ +package com.baeldung.jsonignore.controller; + +import com.baeldung.jsonignore.nullfields.Employee; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping(EmployeeEchoController.USERS) +public class EmployeeEchoController { + + public static final String USERS = "/employees"; + + @PostMapping + public Employee echoUser(@RequestBody Employee employee) { + return employee; + } +} diff --git a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/controller/EmptyEmployeeEchoController.java b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/controller/EmptyEmployeeEchoController.java new file mode 100644 index 0000000000..8024c653e0 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/controller/EmptyEmployeeEchoController.java @@ -0,0 +1,19 @@ +package com.baeldung.jsonignore.controller; + +import com.baeldung.jsonignore.emptyfields.Employee; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping(EmptyEmployeeEchoController.USERS) +public class EmptyEmployeeEchoController { + + public static final String USERS = "/empty_employees"; + + @PostMapping + public Employee echoUser(@RequestBody Employee employee) { + return employee; + } +} diff --git a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/emptyfields/Employee.java b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/emptyfields/Employee.java new file mode 100644 index 0000000000..37171217d8 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/emptyfields/Employee.java @@ -0,0 +1,93 @@ +package com.baeldung.jsonignore.emptyfields; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@JsonInclude(Include.NON_EMPTY) +public class Employee { + + private String lastName; + private String firstName; + private long id; + private Optional salary; + + private String phoneticName = ""; + + private List phoneNumbers = new ArrayList<>(); + + public Employee() { + } + + public Employee(final long id, final String lastName, final String firstName, + final Optional salary, final String phoneticName, final List phoneNumbers) { + this.id = id; + this.lastName = lastName; + this.firstName = firstName; + this.salary = salary; + this.phoneticName = phoneticName != null ? phoneticName : ""; + this.phoneNumbers.addAll(phoneNumbers); + } + + public String getLastName() { + return lastName; + } + + public void setLastName(final String lastName) { + this.lastName = lastName; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(final String firstName) { + this.firstName = firstName; + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public Optional getSalary() { + return salary; + } + + public void setSalary(final Optional salary) { + this.salary = salary; + } + + public String getPhoneticName() { + return phoneticName; + } + + public void setPhoneticName(final String phoneticName) { + this.phoneticName = phoneticName; + } + + public List getPhoneNumbers() { + return phoneNumbers; + } + + public void setPhoneNumbers(final List phoneNumbers) { + this.phoneNumbers = phoneNumbers; + } + + @Override + public String toString() { + return "Employee{" + + "lastName='" + lastName + '\'' + + ", firstName='" + firstName + '\'' + + ", id=" + id + + ", salary=" + salary + + ", phoneticName='" + phoneticName + '\'' + + ", phoneNumbers=" + phoneNumbers + + '}'; + } +} diff --git a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/emptyfields/PhoneNumber.java b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/emptyfields/PhoneNumber.java new file mode 100644 index 0000000000..7353aed739 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/emptyfields/PhoneNumber.java @@ -0,0 +1,28 @@ +package com.baeldung.jsonignore.emptyfields; + +public class PhoneNumber { + + private String number; + + public PhoneNumber() { + } + + public PhoneNumber(final String number) { + this.number = number; + } + + public String getNumber() { + return number; + } + + public void setNumber(final String number) { + this.number = number; + } + + @Override + public String toString() { + return "PhoneNumber{" + + "number='" + number + '\'' + + '}'; + } +} diff --git a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/emptyfields/Salary.java b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/emptyfields/Salary.java new file mode 100644 index 0000000000..d66cbb365a --- /dev/null +++ b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/emptyfields/Salary.java @@ -0,0 +1,30 @@ +package com.baeldung.jsonignore.emptyfields; + +import java.math.BigDecimal; + +public class Salary { + + private BigDecimal hourlyRate; + + public Salary() { + } + + public Salary(BigDecimal hourlyRate) { + this.hourlyRate = hourlyRate; + } + + public BigDecimal getHourlyRate() { + return hourlyRate; + } + + public void setHourlyRate(final BigDecimal hourlyRate) { + this.hourlyRate = hourlyRate; + } + + @Override + public String toString() { + return "Salary{" + + "hourlyRate=" + hourlyRate + + '}'; + } +} diff --git a/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/nullfields/Employee.java b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/nullfields/Employee.java new file mode 100644 index 0000000000..7e8d3f1bb4 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-3/src/main/java/com/baeldung/jsonignore/nullfields/Employee.java @@ -0,0 +1,83 @@ +package com.baeldung.jsonignore.nullfields; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import java.util.Objects; + +@JsonInclude(Include.NON_NULL) +public class Employee { + + private String lastName; + private String firstName; + private long id; + + public Employee() { + } + + public Employee(final long id, final String firstName, final String lastName) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + + public String getLastName() { + return lastName; + } + + public String getFirstName() { + return firstName; + } + + public long getId() { + return id; + } + + public void setLastName(final String lastName) { + this.lastName = lastName; + } + + public void setFirstName(final String firstName) { + this.firstName = firstName; + } + + public void setId(final long id) { + this.id = id; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + final Employee employee = (Employee) o; + + if (id != employee.id) { + return false; + } + if (!Objects.equals(lastName, employee.lastName)) { + return false; + } + return Objects.equals(firstName, employee.firstName); + } + + @Override + public int hashCode() { + int result = lastName != null ? lastName.hashCode() : 0; + result = 31 * result + (firstName != null ? firstName.hashCode() : 0); + result = 31 * result + (int) (id ^ (id >>> 32)); + return result; + } + + @Override + public String toString() { + return "User{" + + "lastName='" + lastName + '\'' + + ", firstName='" + firstName + '\'' + + ", id=" + id + + '}'; + } +} diff --git a/spring-boot-modules/spring-boot-data-3/src/test/java/com/baeldung/jsonignore/AbstractEmployeeEchoControllerBaseIntegrationTest.java b/spring-boot-modules/spring-boot-data-3/src/test/java/com/baeldung/jsonignore/AbstractEmployeeEchoControllerBaseIntegrationTest.java new file mode 100644 index 0000000000..13b181493d --- /dev/null +++ b/spring-boot-modules/spring-boot-data-3/src/test/java/com/baeldung/jsonignore/AbstractEmployeeEchoControllerBaseIntegrationTest.java @@ -0,0 +1,123 @@ +package com.baeldung.jsonignore; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.baeldung.jsonignore.controller.AbsentEmployeeEchoController; +import com.baeldung.jsonignore.controller.EmployeeEchoController; +import com.baeldung.jsonignore.controller.EmptyEmployeeEchoController; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.lang.reflect.Field; +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import org.junit.platform.commons.util.ReflectionUtils; +import org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; + +@WebMvcTest(controllers = {EmployeeEchoController.class, AbsentEmployeeEchoController.class, + EmptyEmployeeEchoController.class}) +abstract class AbstractEmployeeEchoControllerBaseIntegrationTest { + + @Autowired + protected ObjectMapper mapper = new ObjectMapper(); + + @Autowired + protected MockMvc mockMvc; + + protected MvcResult sendRequestAndGetResult(final T expected, final String endpoint) throws Exception { + final String payload = mapper.writeValueAsString(expected); + return mockMvc.perform(post(endpoint) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(payload)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andReturn(); + } + + protected static void nonNullFieldsShouldNonBeMissing(final List nonNullFields, final JsonNode jsonNode) { + nonNullFields.forEach(nullField -> { + final JsonNode nameNode = jsonNode.path(nullField); + assertThat(nameNode.isMissingNode()).isFalse(); + }); + } + + protected static void nullFieldsShouldBeMissing(final List nullFields, final JsonNode jsonNode) { + nullFields.forEach(nullField -> { + final JsonNode nameNode = jsonNode.path(nullField); + assertThat(nameNode.isMissingNode()).isTrue(); + }); + } + + protected static List filterFieldsAndGetNames(final T object, final Predicate predicate) { + return ReflectionUtils.findFields(object.getClass(), predicate, HierarchyTraversalMode.BOTTOM_UP) + .stream().map(Field::getName).collect(Collectors.toList()); + } + + protected static boolean isFieldNull(final T object, final Field s) { + try { + if (Object.class.isAssignableFrom(s.getType())) { + s.setAccessible(true); + return s.get(object) == null; + } else { + return false; + } + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + protected static boolean isFieldAbsent(final T object, final Field s) { + try { + if (Optional.class.isAssignableFrom(s.getType())) { + s.setAccessible(true); + final Optional optional = ((Optional) s.get(object)); + if (optional != null) { + return !optional.isPresent(); + } else { + return false; + } + } else { + return false; + } + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + protected static boolean isFieldEmpty(final T object, final Field s) { + try { + if (String.class.isAssignableFrom(s.getType())) { + s.setAccessible(true); + final String string = ((String) s.get(object)); + if (string != null) { + return string.isEmpty(); + } else { + return false; + } + } else if (Collection.class.isAssignableFrom(s.getType())) { + s.setAccessible(true); + final Collection collection = ((Collection) s.get(object)); + if (collection != null) { + return collection.isEmpty(); + } else { + return false; + } + } else { + return false; + } + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-data-3/src/test/java/com/baeldung/jsonignore/NonAbsentEmployeeFieldsEchoControllerIntegrationTest.java b/spring-boot-modules/spring-boot-data-3/src/test/java/com/baeldung/jsonignore/NonAbsentEmployeeFieldsEchoControllerIntegrationTest.java new file mode 100644 index 0000000000..52ebdca247 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-3/src/test/java/com/baeldung/jsonignore/NonAbsentEmployeeFieldsEchoControllerIntegrationTest.java @@ -0,0 +1,50 @@ +package com.baeldung.jsonignore; + +import static com.baeldung.jsonignore.controller.AbsentEmployeeEchoController.USERS; + +import com.baeldung.jsonignore.absentfields.Employee; +import com.baeldung.jsonignore.absentfields.Salary; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.test.web.servlet.MvcResult; + +class NonAbsentEmployeeFieldsEchoControllerIntegrationTest extends AbstractEmployeeEchoControllerBaseIntegrationTest { + + @ParameterizedTest + @MethodSource + void giveEndpointWhenSendEmployeeThanReceiveThatUserBackIgnoringAbsentValues(final Employee expected) throws Exception { + final MvcResult result = sendRequestAndGetResult(expected, USERS); + final String response = result.getResponse().getContentAsString(); + validateJsonFields(expected, response); + } + + private void validateJsonFields(final Employee expected, final String response) throws JsonProcessingException { + final JsonNode jsonNode = mapper.readTree(response); + final Predicate nullField = s -> isFieldNull(expected, s); + final Predicate absentField = s -> isFieldAbsent(expected, s); + List nullOrAbsentFields = filterFieldsAndGetNames(expected, nullField.or(absentField)); + List nonNullAndNonAbsentFields = filterFieldsAndGetNames(expected, nullField.negate().and(absentField.negate())); + nullFieldsShouldBeMissing(nullOrAbsentFields, jsonNode); + nonNullFieldsShouldNonBeMissing(nonNullAndNonAbsentFields, jsonNode); + } + + static Stream giveEndpointWhenSendEmployeeThanReceiveThatUserBackIgnoringAbsentValues() { + final Salary baseSalary = new Salary(BigDecimal.TEN); + return Stream.of( + Arguments.of(new Employee(1L, "John", "Doe", Optional.empty())), + Arguments.of(new Employee(1L, null, "Doe", Optional.of(baseSalary))), + Arguments.of(new Employee(1L, "John", null, Optional.empty())), + Arguments.of(new Employee(1L, null, null, Optional.of(baseSalary))) + ); + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-data-3/src/test/java/com/baeldung/jsonignore/NonEmptyEmployeeFieldsEchoControllerIntegrationTest.java b/spring-boot-modules/spring-boot-data-3/src/test/java/com/baeldung/jsonignore/NonEmptyEmployeeFieldsEchoControllerIntegrationTest.java new file mode 100644 index 0000000000..12b328a3cb --- /dev/null +++ b/spring-boot-modules/spring-boot-data-3/src/test/java/com/baeldung/jsonignore/NonEmptyEmployeeFieldsEchoControllerIntegrationTest.java @@ -0,0 +1,60 @@ +package com.baeldung.jsonignore; + +import static com.baeldung.jsonignore.controller.EmptyEmployeeEchoController.USERS; + +import com.baeldung.jsonignore.emptyfields.Employee; +import com.baeldung.jsonignore.emptyfields.PhoneNumber; +import com.baeldung.jsonignore.emptyfields.Salary; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.test.web.servlet.MvcResult; + +class NonEmptyEmployeeFieldsEchoControllerIntegrationTest extends AbstractEmployeeEchoControllerBaseIntegrationTest { + + @ParameterizedTest + @MethodSource + void giveEndpointWhenSendEmployeeThanReceiveThatUserBackIgnoringEmptyValues(final Employee expected) throws Exception { + final MvcResult result = sendRequestAndGetResult(expected, USERS); + final String response = result.getResponse().getContentAsString(); + validateJsonFields(expected, response); + } + + private void validateJsonFields(final Employee expected, final String response) throws JsonProcessingException { + final JsonNode jsonNode = mapper.readTree(response); + final Predicate nullField = s -> isFieldNull(expected, s); + final Predicate absentField = s -> isFieldAbsent(expected, s); + final Predicate emptyField = s -> isFieldEmpty(expected, s); + List nullOrAbsentOrEmptyFields = filterFieldsAndGetNames(expected, nullField.or(absentField).or(emptyField)); + List nonNullAndNonAbsentAndNonEmptyFields = filterFieldsAndGetNames(expected, + nullField.negate().and(absentField.negate().and(emptyField.negate()))); + nullFieldsShouldBeMissing(nullOrAbsentOrEmptyFields, jsonNode); + nonNullFieldsShouldNonBeMissing(nonNullAndNonAbsentAndNonEmptyFields, jsonNode); + } + + static Stream giveEndpointWhenSendEmployeeThanReceiveThatUserBackIgnoringEmptyValues() { + final Salary baseSalary = new Salary(BigDecimal.TEN); + final List phones = Arrays.asList(new PhoneNumber("123-456"), new PhoneNumber("789-012")); + return Stream.of( + Arguments.of(new Employee(1L, "John", "Doe", Optional.empty(), "ʤɒn dəʊ", new ArrayList<>())), + Arguments.of(new Employee(1L, null, "Doe", Optional.of(baseSalary), "dəʊ", new ArrayList<>())), + Arguments.of(new Employee(1L, "John", null, Optional.empty(), "ʤɒn", new ArrayList<>())), + Arguments.of(new Employee(1L, null, null, Optional.of(baseSalary), null, new ArrayList<>())), + Arguments.of(new Employee(1L, "John", "Doe", Optional.empty(), "ʤɒn dəʊ", phones)), + Arguments.of(new Employee(1L, null, "Doe", Optional.of(baseSalary), "dəʊ", phones)), + Arguments.of(new Employee(1L, "John", null, Optional.empty(), "ʤɒn", phones)), + Arguments.of(new Employee(1L, null, null, Optional.of(baseSalary), null, phones)) + ); + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-data-3/src/test/java/com/baeldung/jsonignore/NonNullEmployeeFieldsEchoControllerIntegrationTest.java b/spring-boot-modules/spring-boot-data-3/src/test/java/com/baeldung/jsonignore/NonNullEmployeeFieldsEchoControllerIntegrationTest.java new file mode 100644 index 0000000000..6bac80219d --- /dev/null +++ b/spring-boot-modules/spring-boot-data-3/src/test/java/com/baeldung/jsonignore/NonNullEmployeeFieldsEchoControllerIntegrationTest.java @@ -0,0 +1,45 @@ +package com.baeldung.jsonignore; + +import static com.baeldung.jsonignore.controller.EmployeeEchoController.USERS; + +import com.baeldung.jsonignore.nullfields.Employee; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import java.lang.reflect.Field; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.test.web.servlet.MvcResult; + +class NonNullEmployeeFieldsEchoControllerIntegrationTest extends AbstractEmployeeEchoControllerBaseIntegrationTest { + + @ParameterizedTest + @MethodSource + void giveEndpointWhenSendEmployeeThanReceiveThatUserBackIgnoringNullValues(final Employee expected) throws Exception { + final MvcResult result = sendRequestAndGetResult(expected, USERS); + final String response = result.getResponse().getContentAsString(); + validateJsonFields(expected, response); + } + + private void validateJsonFields(final Employee expected, final String response) throws JsonProcessingException { + final JsonNode jsonNode = mapper.readTree(response); + final Predicate nullField = s -> isFieldNull(expected, s); + List nullFields = filterFieldsAndGetNames(expected, nullField); + List nonNullFields = filterFieldsAndGetNames(expected, nullField.negate()); + nullFieldsShouldBeMissing(nullFields, jsonNode); + nonNullFieldsShouldNonBeMissing(nonNullFields, jsonNode); + } + + static Stream giveEndpointWhenSendEmployeeThanReceiveThatUserBackIgnoringNullValues() { + return Stream.of( + Arguments.of(new Employee(1L, "John", "Doe")), + Arguments.of(new Employee(1L, null, "Doe")), + Arguments.of(new Employee(1L, "John", null)), + Arguments.of(new Employee(1L, null, null)) + ); + } + +} \ No newline at end of file