skip to content

What is @JsonTest and what does JacksonTester give you?

level: juniorimportance: should knowfreq 42%

answer

  1. Slice = JSON layer only
  2. Uses app's real ObjectMapper + @JsonComponent
  3. JacksonTester.write -> JsonContent
  4. parseObject -> back to object
  5. extractingJsonPath... / isEqualToJson(file)

basics

~20 s

@JsonTest is a Spring Boot slice for testing JSON serialization. It configures your app's Jackson (or Gson) setup and gives you a JacksonTester helper to serialize/deserialize objects and assert the resulting JSON, without starting the whole app.

solid answer

~30 s

@JsonTest is a narrow Spring Boot test slice that loads only the JSON infrastructure — your application's configured Jackson `ObjectMapper` (plus Gson/JSON-B if present), including any custom modules and `@JsonComponent` beans. It then provides tester helpers you `@Autowired`: `JacksonTester<T>` (and `GsonTester`, `JsonbTester`, `BasicJsonTester`). `JacksonTester.write(obj)` serializes an object to a `JsonContent`, on which you run AssertJ-style assertions like `extractingJsonPathStringValue("$.name")` or `isEqualToJson("expected.json")` to compare against a classpath file. `parse`/`parseObject` deserialize JSON back into objects. It is faster and more focused than @SpringBootTest and lets you pin the exact wire format of your DTOs — field names, formatting, null handling — in isolation.

code

java · 21 lines
java
@JsonTest
class EmployeeJsonTest {

    @Autowired
    private JacksonTester<Employee> json; // auto-initialized by the slice

    @Test
    void serializesToExpectedShape() throws Exception {
        JsonContent<Employee> result = json.write(new Employee("Ada", 42));

        assertThat(result).extractingJsonPathStringValue("$.name").isEqualTo("Ada");
        assertThat(result).extractingJsonPathNumberValue("$.age").isEqualTo(42);
        assertThat(result).isEqualToJson("employee.json"); // classpath file
    }

    @Test
    void deserializesFromJson() throws Exception {
        Employee e = json.parseObject("{\"name\":\"Ada\",\"age\":42}");
        assertThat(e.getName()).isEqualTo("Ada");
    }
}

go deeper

for a junior

Know it tests JSON serialization with JacksonTester and assertions like isEqualToJson.

for a middle

Explain that it loads the app's real Jackson config (modules, @JsonComponent) and how to serialize vs deserialize and assert JSON paths.

for a senior

Discuss pinning wire contracts, lenient vs strict compare, JsonContent path assertions, and when to prefer @JsonTest over @WebMvcTest.

for a principal

Frame @JsonTest as contract-testing for DTOs, note coupling to global Jackson config, and set team conventions for expected-JSON fixtures and enum/date representations.

## What it is `@JsonTest` (`org.springframework.boot.test.autoconfigure.json.JsonTest`) is a Spring Boot **test slice** that stands up only the **JSON marshalling layer** of your app — not controllers, not the DB, not services. ## What it auto-configures It applies your application's JSON configuration so the test uses the *same* serialization rules as production: - the auto-configured **Jackson `ObjectMapper`** with all registered Jackson **modules** (e.g. JavaTime for `java.time`) and any **`@JsonComponent`** custom serializers/deserializers you defined, - **Gson** and **JSON-B** equivalents if those libraries are on the classpath, - and the **tester** helper beans. ## The testers You inject a typed tester as a field: - **`JacksonTester<T>`** — Jackson-backed; the most common. - **`GsonTester<T>`**, **`JsonbTester<T>`** — same idea for Gson / JSON-B. - **`BasicJsonTester`** — not typed; works on raw JSON strings for path assertions only (no object binding). Key methods on `JacksonTester<T>`: - **`write(T object)`** → returns a **`JsonContent<T>`** (serialization / 'object → JSON'). - **`parse(String json)`** → `ObjectContent<T>`; **`parseObject(String json)`** → the `T` instance directly (deserialization / 'JSON → object'). - `read(...)` overloads read JSON from classpath resources. ## Assertions `JsonContent` integrates with AssertJ via `assertThat(...)`: - **JSON-path value checks**: `extractingJsonPathStringValue("$.name").isEqualTo("Ada")`, `...NumberValue`, `...BooleanValue`, `...ArrayValue`, plus `hasJsonPathValue`/`doesNotHaveJsonPath`. - **Whole-document compare**: `isEqualToJson("employee.json")` compares (order-insensitively) against a JSON file on the classpath, or `isStrictlyEqualToJson(...)`. This uses the underlying JSONAssert/JsonPath support. ## How the tester gets initialized Because `JacksonTester<T>` is generic, it needs the field's type info. Under `@JsonTest`, Spring Boot **initializes any tester fields automatically** (it calls `JacksonTester.initFields(...)` for you). If you construct the test object yourself outside the slice, you must call `JacksonTester.initFields(this, objectMapper)` manually — otherwise the tester is null. ## When to use it Use `@JsonTest` to lock down the **exact wire contract** of your DTOs: property names, date/number formatting, enum representation, `@JsonIgnore`/`@JsonProperty` behavior, and round-trip fidelity — cheaply and in isolation, independent of any controller. For a full controller-plus-JSON test you'd use `@WebMvcTest`, but that is heavier and mixes concerns. ## Gotchas - A `NullPointerException` on the tester usually means it was not initialized (test not run under the slice, or `initFields` missing). - `isEqualToJson("file.json")` resolves the file **relative to the test class package** on the classpath by default. - The slice honors your real Jackson config, so a global setting (e.g. `WRITE_DATES_AS_TIMESTAMPS=false`) affects the output — that is the point, but it can surprise you.

  • Your JacksonTester field is null at runtime — what went wrong?
    The tester was not initialized. Under @JsonTest Spring auto-calls JacksonTester.initFields; if you instantiate the test outside the slice you must call JacksonTester.initFields(this, objectMapper) yourself, or the generic tester stays uninitialized/null.
  • Difference between isEqualToJson and extractingJsonPathStringValue?
    isEqualToJson compares the whole document against an expected JSON (file or string), order-insensitively by default. extractingJsonPathStringValue asserts a single value at a JSON path, useful when you only care about specific fields.

saying these in an interview costs you the question

  • Thinking @JsonTest starts controllers or the web layer (that is @WebMvcTest).
  • Believing it uses a fresh default ObjectMapper rather than the app's configured one.
  • Confusing write() (serialize) with parse()/parseObject() (deserialize).
  • Assuming isEqualToJson does a strict, order-sensitive compare by default (it is lenient; use isStrictlyEqualToJson for strict).

context