I have a Spring Boot 2.3.2.RELEASE
WebFlux application. I have some JPA entities that are returned as part of the RESTful API responses.
The tests that I have (using @WebFluxTest
) check the HTTP response(s) and contract — against a JSON schema. I'm injecting a Jackson's ObjecMapper
and a Spring WebTestClient
in those tests to check the HTTP response(s) against the corresponding/expected JSON schema.
The problem is: if I use any HTTP client when the application is running, the collections (on the Java side) with no elements are serialized into JSON as empty arrays — that's what I would expect regardless of whether that's right or wrong theoretically; but on the test cases, the same empty collections are being serialized with null
values.
So I wonder why would that be different? I would expect the same JSON string at any point.
I know I'm not using different ObjectMapper
settings — or that's what I think. I don't have any custom Spring beans for that type, so I'm using whatever Spring Boot injects by default, so it must be the same for the running application as well as when running the tests. The only customization for Jackson is done at the application level in the application.yml
:
spring:
...
jackson:
property-naming-strategy: LOWER_CAMEL_CASE
serialization:
write-date-timestamps-as-nanoseconds: false
write-dates-as-timestamps: true
...
I'm using the
com.networknt:json-schema-validator:1.0.43
library for the JSON schema implementation.
Excerpt of one of the test cases:
@WebFluxTest(controllers = [ExamController::class])
internal class ExamControllerTest {
@Autowired
private lateinit var webClient: WebTestClient
@Autowired
private lateinit var mapper: ObjectMapper
@Test
@Disabled
fun getById_ValidateResponseAgainstSchema() {
// IMPORTANT: If you update anything here, make the corresponding changes also to getById_WhenRecordExists
webClient.get()
.uri("/exams/10001030")
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus().isOk
.expectBody()
.consumeWith { result ->
val schemaFactory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V201909)
this::class.java.getResourceAsStream("/json-schemas/exam/exam-details.json").use {
Assertions.assertThat(schemaFactory.getSchema(it).validate(mapper.readTree(result.responseBody))).isEmpty()
}
}
}
// ...
}
The test data is created/seeded in a Docker container using Testcontainers.
Disable the DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT
, so that Jackson doesn‘t deserialize empty arrays as null values