为什么使用Webflux进行弹簧启动测试会忽略自定义杰克逊模块

爱神

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

当我运行应用程序时,此设置就像一个超级按钮。实例化该Bean,并使用正确的序列化程序对REST响应进行序列化。

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

我创建了一个小型演示项目来重现该问题。完整的代码可以在这里找到: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运行实际应用程序时,已正确拾取此bean并将其添加到中

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

        return serializerModule;
    }
}

我还验证了该测试中确实存在该bean。因此,我可以排除在测试期间创建的上下文缺少加载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上进行了大量搜索,但是到目前为止,我发现的解决方案都没有帮助。另外,到目前为止,几乎没有人使用路由器功能:)。

任何帮助表示赞赏!

更新:我尝试了2.0.2.RELEASE和2.1.0.BUILD-20180509。结果总是一样的。

塞巴斯蒂安·德勒兹(Sebastien Deleuze)

除了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\"}");
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

忽略杰克逊/春/ Java的根节点和自定义映射

如何提供与杰克逊和Spring启动自定义解串器

杰克逊自定义反序列化器无法在春季启动中工作

杰克逊自定义序列化对象

自定义值序列杰克逊定制的注解

杰克逊:解析自定义偏移日期时间

自定义日期字符串使用杰克逊JsonFormat模式

使用杰克逊的对象数组的自定义序列化器

使用杰克逊可自定义序列化和反序列化

杰克逊使用其他字段的哈希值添加自定义字段

无法获取jersey 2应用程序以使用自定义杰克逊XmlMapper

弹簧启动杰克逊单个对象作为数组

如何使用杰克逊遍历生成的JSON模式并将自定义属性放入JSON模式

杰克逊使用自定义日期格式错误地反序列化Joda日期

如何在春季应用中注册自定义杰克逊滤波器?

捕获和处理异常杰克逊用一个自定义消息

杰克逊:在自定义字段JsonDeserializer中获取整个对象

杰克逊全局设置deserialise数组自定义列表实施

在自定义序列化器杰克逊内部配置objectmapper?

自定义JSON序列化从Java科特林元杰克逊

杰克逊自定义序列化和反序列化

如何自定义序列化杰克逊日期,@JsonSerialize不工作

杰克逊:如何使@JsonBackReference和自定义解串器同时工作?

SpringBoot 2.2.2:杰克逊串行自定义分页不起作用

杰克逊:反序列化的自定义XML中的属性POJO

全POJO数据绑定杰克逊自定义过滤器

用杰克逊反序列化为自定义对象的HashMap

杰克逊中用于枚举的自定义xml解串器

杰克逊:反序列化map <String,Object>到自定义嵌套Pojo

TOP 榜单

热门标签

归档