Adam
Adam

Reputation: 5455

How to create JSON for integration tests with spring-data-rest and MockMvc

I'm using spring-data-rest on top of spring-data-jpa.

I'm writing integration tests to test my SDR API using MockMvc and an in-memory testing database.

Until now, I concentrated on the GETs, but now I'm looking at creating tests for the POST, PUT and PATCH requests and it looks like I'll have to write my own JSON generator (perhaps based on GSON) in order to get stuff like URLs for related entities e.g.

public class ForecastEntity {
    @RestResource
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "UNITID", referencedColumnName = "ID")
    private UnitEntity unit;
}

and in my tests I would build up an entity with parent / children:

ForecastEntity forecast = new ForecastEntity();
forecast.setTitle("test-forecast");
forecast.setUnit(new UnitEntity("test-unit"));

should generate JSON like this:

{
    "title" : "test-forecast",
    "unit" : "http://localhost/units/test-unit"
}

Is there functionality in SDR that I can use to produce JSON from manually initialized entities in tests?

Upvotes: 2

Views: 4817

Answers (2)

tequilacat
tequilacat

Reputation: 757

Mathias, thanks for the great idea.

I came up with a simple method to be used in tests:

public static String toJson(String ... args) throws JsonProcessingException {
  Builder<String, String> builder = ImmutableMap.builder();
  for(int i = 0; i < args.length; i+=2){
    builder.put(args[i], args[i+1]);
  }
  return new ObjectMapper().writeValueAsString(builder.build());
}

I use it like this:

mockMvc.perform(patch(someUri)
  .contentType(APPLICATION_JSON)
  .content(toJson("title", "test-forecast", "unit", "http://localhost/units/test-unit")));

Upvotes: 0

Mathias Dpunkt
Mathias Dpunkt

Reputation: 12184

I tend to build a Map that represent the Json and serialize it into a string that I in turn use as the content of the e.g. POST call.

For convenience I like to use guava ImmutableMap because it comes with handy builder functionality.

String json = new ObjectMapper().writeValueAsString(ImmutableMap.builder()
    .put("title", "test-forecast")
    .put("unit", "http://localhost/units/test-unit")
    .build());
mockMvc.perform(patch(someUri)
    .contentType(APPLICATION_JSON)
    .content(json));

Of course you could also directly serialize an instance of your entity with the `ObjectMapper``

ForecastEntity forecast = new ForecastEntity();
forecast.setTitle("test-forecast");
forecast.setUnit(new UnitEntity("test-unit"));
String json = new ObjectMapper().writeValueAsString(forecast)

I like to go with the first version because with this approach it is very explicit which json you send. And you immediately realize when you make incompatible changes.

Upvotes: 2

Related Questions