简体   繁体   中英

RestAssured does not respect ObjectMapper configuration in Quarkus

I've made a very simple adjustment to the ObjectMapper configuration in my Quarkus application, as described per the Quarkus guides:

@Singleton
public class ObjectMapperConfig implements ObjectMapperCustomizer {

    @Override
    public void customize(ObjectMapper objectMapper) {
        objectMapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
        objectMapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
        objectMapper.registerModule(new JavaTimeModule());
    }

}

I've done this to wrap/unwrap my objects with the @JsonRootName annotation:

@RegisterForReflection
@JsonRootName("article")
public class CreateArticleRequest {

    private CreateArticleRequest(String title, String description, String body, List<String> tagList) {
        this.title = title;
        this.description = description;
        this.body = body;
        this.tagList = tagList;
    }

    private String title;
    private String description;
    private String body;
    private List<String> tagList;

    ... 

}

This works just fine when curl against my actual API, but whenever I use RestAssured in one of my tests, RestAssured does not seem to respect my ObjectMapper config, and does not wrap the CreateArticleRequest as it should be doing as indicated by the @JsonRootName annotation.

@QuarkusTest
public class ArticleResourceTest {

    @Test
    public void testCreateArticle() {
        given()
            .when()
            .body(CREATE_ARTICLE_REQUEST)
            .contentType(ContentType.JSON)
            .log().all()
            .post("/api/articles")
            .then()
            .statusCode(201)
            .body("", equalTo(""))
            .body("article.title", equalTo(ARTICLE_TITLE))
            .body("article.favorited", equalTo(ARTICLE_FAVORITE))
            .body("article.body", equalTo(ARTICLE_BODY))
            .body("article.favoritesCount", equalTo(ARTICLE_FAVORITE_COUNT))
            .body("article.taglist", equalTo(ARTICLE_TAG_LIST));
    }

}

This serializes my request body as:

{
    "title": "How to train your dragon",
    "description": "Ever wonder how?",
    "body": "Very carefully.",
    "tagList": [
        "dragons",
        "training"
    ]
}

... instead of...

{
    "article": {
        "title": "How to train your dragon",
        "description": "Ever wonder how?",
        "body": "Very carefully.",
        "tagList": [
            "dragons",
            "training"
        ]
    }
}

I can actually fix this, by manually configuring the RestAssured ObjectMapper, like so:

@QuarkusTest
public class ArticleResourceTest {

    @BeforeEach
    void setUp() {
        RestAssured.config = RestAssuredConfig.config().objectMapperConfig(new ObjectMapperConfig().jackson2ObjectMapperFactory(
            (cls, charset) -> {
                ObjectMapper mapper = new ObjectMapper().findAndRegisterModules();
                mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
                mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
                mapper.registerModule(new JavaTimeModule());
                return mapper;
            }
        ));
    }
}

However, I obviously do not want to do this. I wanted RestAssured to pick up my ObjectMapper config so that I don't need to keep around two different ObjectMapper configurations.

Why is it not being picked up? What am I missing?

So actually Quarkus won't be doing this automatically (due to the fact that it would interfere with the native tests).

You can however use:

@Inject
ObjectMapper

inside the test to setup RestAssured.config

Just to update in case someone find this like me...

I just add the Singleton ObjectMapperConfig and this is working on

<quarkus.platform.version>2.3.0.Final</quarkus.platform.version>

    <dependency>
      <groupId>io.rest-assured</groupId>
      <artifactId>rest-assured</artifactId>
      <scope>test</scope>
    </dependency>

I solved this with

@QuarkusTest
public class RESTResourceTest {

    @Inject
    ObjectMapper mapper;

    @BeforeEach
    void setUp() {
        RestAssured.config = RestAssured.config().objectMapperConfig(new ObjectMapperConfig().jackson2ObjectMapperFactory( (cls, charset) -> mapper ));
    }

where somewhere else in my src/main/java I have my custom ObjectMapper customizer:

import javax.inject.Singleton;

import com.fasterxml.jackson.databind.ObjectMapper;

import io.cloudevents.jackson.JsonFormat;
import io.quarkus.jackson.ObjectMapperCustomizer;

@Singleton
public class QuarkusObjectMapperCustomizer implements ObjectMapperCustomizer {

    public void customize(ObjectMapper mapper) {
        mapper.registerModule(JsonFormat.getCloudEventJacksonModule());
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM