为什么使用 webflux 进行 Spring Boot 测试会忽略自定义 Jackson 模块

2023-12-31

我正在使用 Spring Boot 2.0.1 和 WebFlux 路由器功能编写一个应用程序(not基于注释!)。对于我的一些数据对象,我编写了扩展的自定义序列化器StdSerializer。这些我注册在SimpleModule并将该模块公开为 bean。

当我运行该应用程序时,此设置非常有效。该 bean 已实例化,并且使用正确的序列化器序列化 REST 响应。

现在我想编写一个测试来验证路由器功能及其背后的处理程序是否按预期工作。我想模拟的处理程序背后的服务。然而,在测试中,REST 响应使用默认序列化器.

我创建了一个小型演示项目来重现该问题。完整代码可以在这里找到:http://s000.tinyupload.com/?file_id=82815835861287011625 http://s000.tinyupload.com/?file_id=82815835861287011625

Gradle 配置加载 Spring Boot 和一些依赖项来支持 WebFlux 和测试。

import io.spring.gradle.dependencymanagement.DependencyManagementPlugin
import org.springframework.boot.gradle.plugin.SpringBootPlugin

buildscript {
    ext {
        springBootVersion = '2.0.1.RELEASE'
    }
    repositories {
        mavenCentral()
        // To allow to pull in milestone releases from Spring
        maven { url 'https://repo.spring.io/milestone' }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("io.spring.gradle:dependency-management-plugin:1.0.5.RELEASE")

    }
}

apply plugin: 'java'
apply plugin: SpringBootPlugin
apply plugin: DependencyManagementPlugin


repositories {
    mavenCentral()

    // To allow to pull in milestone releases from Spring
    maven { url 'https://repo.spring.io/milestone' }
}

dependencyManagement {
    imports {
        mavenBom 'org.springframework.boot:spring-boot-dependencies:2.0.1.RELEASE'
    }
}

dependencies {
    compile 'org.springframework.boot:spring-boot-starter-webflux'

    compile 'org.slf4s:slf4s-api_2.12:1.7.25'

    testCompile 'org.springframework.boot:spring-boot-starter-test'
    testCompile 'org.springframework.boot:spring-boot-starter-json'
    testCompile 'junit:junit:4.12'
    testCompile "org.mockito:mockito-core:2.+"
}

数据对象有两个字段。

package com.example.model;

public class ReverserResult {
    private String originalString;
    private String reversedString;

    // ... constructor, getters
}

自定义序列化程序以与默认序列化程序完全不同的方式呈现数据对象。原始字段名称消失,数据对象的内容被压缩为单个字符串。

@Component
public class ReverserResultSerializer extends StdSerializer<ReverserResult> {
    // ... Constructor ...

    @Override
    public void serialize(ReverserResult value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        gen.writeFieldName("result");
        gen.writeString(value.getOriginalString() + "|" + value.getReversedString());
        gen.writeEndObject();
    }
}

序列化器封装在 Jackson 模块中并作为 bean 公开。该豆子被正确拾取并添加到ObjectMapper运行实际应用程序时。

@Configuration
public class SerializerConfig {
    @Bean
    @Autowired public Module specificSerializers(ReverserResultSerializer reverserResultSerializer) {
        SimpleModule serializerModule = new SimpleModule();
        serializerModule.addSerializer(ReverserResult.class, reverserResultSerializer);

        return serializerModule;
    }
}

我还验证了测试中确实存在该豆。因此我可以排除在测试期间创建的上下文缺少加载 bean 的情况。

@RunWith(SpringRunner.class)
@SpringBootTest
public class ReverserRouteTest {
    @Autowired
    public ReverserRoutes reverserRoutes;

    @MockBean
    public ReverserService mockReverserService;

    @Autowired
    @Qualifier("specificSerializers")
    public Module jacksonModule;

    @Test
    public void testSerializerBeanIsPresent() {
        assertNotNull(jacksonModule);
    }

    @Test
    public void testRouteAcceptsCall() {
        given(mockReverserService.reverse(anyString())).willReturn(new ReverserResult("foo", "bar"));

        WebTestClient client = WebTestClient.bindToRouterFunction(reverserRoutes.createRouterFunction()).build();
        client.get().uri("/reverse/FooBar").exchange().expectStatus().isOk();
    }

    @Test
    public void testRouteReturnsMockedResult() {
        given(mockReverserService.reverse(anyString())).willReturn(new ReverserResult("foo", "bar"));

        WebTestClient client = WebTestClient.bindToRouterFunction(reverserRoutes.createRouterFunction()).build();
        client.get().uri("/reverse/somethingcompletelydifferent")
                .exchange()
                .expectBody().json("{\"result\":\"foo|bar\"}");
    }
}

运行应用程序时的结果:

GET http://localhost:9090/reverse/FooBar

HTTP/1.1 200 OK
transfer-encoding: chunked
Content-Type: application/json;charset=UTF-8

{
  "result": "FooBar|raBooF"
}

运行测试时的结果:

< 200 OK
< Content-Type: [application/json;charset=UTF-8]

{"originalString":"foo","reversedString":"bar"}

我还尝试创建自己的 ObjectMapper 实例,但也没有使用。我想知道我是否缺少一个设置(不过我确实尝试了很多注释......)或者我是否遇到了错误。我在 Google 和 SO 上进行了大量搜索,但到目前为止我发现的解决方案都没有帮助。另外,到目前为止,很少有人使用路由器功能:)。

任何帮助表示赞赏!

UPDATE:我也尝试过 2.0.2.RELEASE 和 2.1.0.BUILD-20180509 。结果总是一样的。


而不是创建一个WebTestClient在测试中手动,您可能可以利用@AutoConfigureWebTestClient并按如下方式自动装配它,以便正确考虑您的 Jackson 模块:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureWebTestClient
public class ReverserRouteTest {    
    @MockBean
    public ReverserService mockReverserService;

    @Autowired
    @Qualifier("specificSerializers")
    public Module jacksonModule;

    @Autowired
    public WebTestClient client;

    @Test
    public void testSerializerBeanIsPresent() {
        assertNotNull(jacksonModule);
    }

    @Test
    public void testRouteAcceptsCall() {
        given(mockReverserService.reverse(anyString())).willReturn(new ReverserResult("foo", "bar"));

        client.get().uri("/reverse/FooBar").exchange().expectStatus().isOk();
    }

    @Test
    public void testRouteReturnsMockedResult() {
        given(mockReverserService.reverse(anyString())).willReturn(new ReverserResult("foo", "bar"));

        client.get().uri("/reverse/somethingcompletelydifferent")
                .exchange()
                .expectBody().json("{\"result\":\"foo|bar\"}");
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么使用 webflux 进行 Spring Boot 测试会忽略自定义 Jackson 模块 的相关文章

随机推荐

  • 如何在gridview中间歇性地展示横幅广告

    I am developing an android app that will have a screen similar to the following image 请注意单元格之间的横幅广告 由于 GridView 不支持这种跨列
  • 为什么在 epoll 中推荐使用非阻塞套接字

    我正在尝试学习如何将 epoll 用于 tcp 服务器应用程序 因为我期望有很多连接 我尝试检查示例和教程 他们总是建议使用 设置在 epoll 中添加的套接字为非阻塞套接字 为什么 对于级别触发的 epoll 非阻塞套接字可以帮助最大限度
  • C# Groupby 然后在分割 CSV 后求和(无标题)

    阅读了各种帖子后 我认为我已经接近得到我想要的结果 但 总和 部分给出了错误的答案 我怀疑这是由于我调用 总和 的方式造成的 因为我的 csv 文件没有列标题 csv 文件包含以下内容 222 1 223 2 222 1 224 2 222
  • 偏移GPS坐标的公式/算法

    我以纬度 经度的形式提供 GPS 坐标 并希望将它们偏移距离和角度 例如 如果我偏移 新坐标是多少45 12345 7 34567沿方位 104 度行驶 22 公里 Thanks 对于大多数应用 这两个公式之一就足够了 给定径向和距离的纬度
  • 收到错误 /bin/sh: 1: 源: 未找到

    我正在尝试构建 docker 并安装 nvm 一些代码行 RUN curl https raw githubusercontent com creationix nvm v0 25 0 install sh bash RUN source
  • 使用 Visual Studio 扩展设置光标位置

    我正在编写自己的 Visual Studio 2010 扩展 它应该可以帮助我浏览一个相当大的解决方案 我已经有一个基于对话框的 VS 扩展 它根据某些搜索条件显示类名和函数名 我现在可以单击此类 方法 然后我就可以打开正确的文件并跳转到该
  • C# OpenGL字体显示

    我正在Windows中使用Tao框架开发2D CAD应用程序 我想使用 Windows 库中的字体来显示绘图信息 除此之外 我想旋转缩放我的文本 对于位图字体我无法做到这一点 我进行了 OpenGL 字体调查 http www opengl
  • SQL-合并两个具有不同日期值的表

    我正在开发一个在网站上显示股票信息的项目 我想问一下如何在SQL中合并两个表 假设我们有表1 stock id date p high p low 3 2013 02 26 100 80 3 2013 02 25 100 80 3 2013
  • 如何使用python获取一列数据中包含的特定行的时间差

    这里我有一个包含时间和三个输入的数据集 这里我用panda来计算时差 代码是 data Time different pd to timedelta data time astype str diff 1 dt total seconds
  • 为什么要创建“隐式解包选项”,因为这意味着您知道有一个值?

    为什么要创建 隐式解包可选 而不是仅创建常规变量或常量 如果您知道它可以成功解包 那么为什么首先要创建一个可选呢 例如 这是为什么 let someString String this is the string 将比以下更有用 let s
  • 代码高尔夫:井字棋

    Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案或互动 按字符数发布您的最短代码 以检查玩家是否获胜 如果获胜 是哪一个 假设变量中有一个整数数组b
  • 重命名 ASP.NET Identity 表时出现重复的外键

    我遵循了以下建议这个问题 https stackoverflow com questions 19460386 how can i change the table names when using visual studio 2013 a
  • 参数包扩展的“模式”定义,尤其是在函数调用中

    据我了解 当包含参数包的模式右侧出现省略号 时 该模式将为包中的每个参数扩展一次 然而 尽管我能够找到模式及其扩展的孤立示例 但我无法找到模式构成的定义 据我所知 空格在模式的定义中不起任何作用 但括号却起作用 例如 在这个例子中 temp
  • 在 sbt 控制台上运行 Spark

    我是 Spark 新手 正在尝试在 sbt 控制台上运行它 我有一个合适的build sbt 因为代码在 Intellij 上运行良好 并且能够导入代码中的包 问题是 当在 sbt 控制台 终端 上运行时 执行器只是保持运行并且无法完成任务
  • android 阿拉伯语十进制格式,符号位于数字右侧

    我正在尝试支持左语言的 RTL 并且正在使用阿拉伯语进行测试 我对此一无所知 负号 正号应该位于数字的右侧还是左侧 我认为它应该在左侧 但是当我使用 Android 的 DecimalFormat 将数字放入设备设置的区域设置时 该符号出现
  • 候选者的 UITableView 类型不匹配?

    Xcode 说 候选者的 UITableView 类型不匹配 有人知道如何解决这个问题吗 func tableView tableView UITableView numberOfRowsInSection section Int gt I
  • C++ 11 代码可以使用 `clang++` 进行编译,但不能使用 `clang -x c++` 进行编译

    基本问题 我有以下代码 include
  • Android SQLite删除行问题

    我正在尝试从表中删除一行 但我有三个 WHERE 子句 并且不确定我是否使用了正确的语句 db delete DBAdapter TableName Id Id AND WHERE QstnrId Integer parseInt Ques
  • 使用 github 操作创建拉取请求

    我试图让它发挥作用 但我也很困惑 在触发彼得埃文斯公关之前 它之间缺少什么 这个场景非常简单 我喜欢在任何 feature 分支上推送 自动创建 PR 但相反 我遇到了奇怪的场景 其中开发更改应用于 feature 分支之上 有人可以给我提
  • 为什么使用 webflux 进行 Spring Boot 测试会忽略自定义 Jackson 模块

    我正在使用 Spring Boot 2 0 1 和 WebFlux 路由器功能编写一个应用程序 not基于注释 对于我的一些数据对象 我编写了扩展的自定义序列化器StdSerializer 这些我注册在SimpleModule并将该模块公开