RestAssured 不尊重 Quarkus 中的 ObjectMapper 配置

Posted

技术标签:

【中文标题】RestAssured 不尊重 Quarkus 中的 ObjectMapper 配置【英文标题】:RestAssured does not respect ObjectMapper configuration in Quarkus 【发布时间】:2020-03-06 18:10:50 【问题描述】:

我对我的 Quarkus 应用程序中的 ObjectMapper 配置进行了非常简单的调整,如 Quarkus 指南所述:

@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());
    


我这样做是为了使用 @JsonRootName 注释来包装/解开我的对象:

@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;

    ... 


curl 针对我的实际 API 时,这工作得很好,但是每当我在我的一个测试中使用 RestAssured 时,RestAssured 似乎不尊重我的 ObjectMapper 配置,并且不包装 CreateArticleRequest,因为它应该按照指示做通过@JsonRootName 注释。

@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));
    


这将我的请求正文序列化为:


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

...而不是...


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

我实际上可以通过手动配置 RestAssured ObjectMapper 来解决这个问题,如下所示:

@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;
            
        ));
    

但是,我显然不想这样做!我希望 RestAssured 获取我的 ObjectMapper 配置,这样我就不需要保留两个不同的 ObjectMapper 配置。

为什么没有收到?我错过了什么?

【问题讨论】:

这是一个很好的功能请求恕我直言!能否请您打开一个问题并 ping 我(github 上的@geoand)? 我已经有了这个工作的原型。只是需要一些清理。一旦我在 Github 上打开拉取请求,我就会回帖。 添加该功能的 PR 已打开:github.com/quarkusio/quarkus/pull/5430 【参考方案1】:

所以实际上 Quarkus 不会自动执行此操作(因为它会干扰原生测试)。

但是你可以使用:

@Inject
ObjectMapper

在测试内部设置RestAssured.config

【讨论】:

【参考方案2】:

只是为了更新,以防有人发现像我这样......

我只是添加了 Singleton ObjectMapperConfig,这正在运行

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

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

【讨论】:

【参考方案3】:

我解决了这个问题

@QuarkusTest
public class RESTResourceTest 

    @Inject
    ObjectMapper mapper;

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

在我的 src/main/java 的其他地方我有我的自定义 ObjectMapper 定制器:

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());
    

【讨论】:

以上是关于RestAssured 不尊重 Quarkus 中的 ObjectMapper 配置的主要内容,如果未能解决你的问题,请参考以下文章

导入 io.restassured.RestAssured 无法解析

线程“ main”中的异常java.lang.NoClassDefFoundError:io / restassured / RestAssured

收到响应后,是不是可以选择删除 REST API(RestAssured) 中请求中设置的多部分内容?

RestAssured 获取请求中的 pathParam() 方法出现红色下划线错误以及如何解决此问题

quarkus: IllegalStateException: 你试图对一个IO线程进行阻塞操作。这是不允许的,因为阻塞IO线程

RestAssured assertThat,键的通配符