You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot 3.2 WebFlux测试中自定义Jackson序列化器未生效问题

解决方案:SpringBoot 3.2 WebFlux测试中自定义Jackson MoneyModule不生效问题

问题根源

  1. @WebFluxTest 环境下,Spring Boot会自动配置WebFlux专属的Jackson组件,直接注册ObjectMapper Bean不会被WebTestClient识别,必须通过Jackson2ObjectMapperBuilderCustomizer来定制全局Jackson配置。
  2. 自定义MoneyModule中手动实例化序列化器/反序列化器,未利用Spring依赖注入,导致实例脱离Spring上下文管理。
  3. 错误提示指向抽象类MonetaryAmount,但自定义反序列化器仅注册给了具体实现类Money,Jackson无法关联抽象类到对应处理逻辑。

修复步骤

1. 修改Jackson配置类,改用Jackson2ObjectMapperBuilderCustomizer

替换直接创建ObjectMapper的方式,通过Spring官方推荐的定制器来注册模块:

@Configuration
public class JacksonConfig {
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() {
        return builder -> {
            builder.modules(new MoneyModule(), new JavaTimeModule());
        };
    }
}

2. 将MoneyModule转为Spring组件,注入序列化器实例

让Spring管理MoneyModule,并通过构造注入获取序列化器/反序列化器的Spring托管实例,同时覆盖抽象类MonetaryAmount的处理逻辑:

@Component
public class MoneyModule extends SimpleModule {
    private final MoneySerializer moneySerializer;
    private final MoneyDeserializer moneyDeserializer;

    public MoneyModule(MoneySerializer moneySerializer, MoneyDeserializer moneyDeserializer) {
        super();
        // 注册具体类型Money的序列化/反序列化
        addSerializer(Money.class, moneySerializer);
        addDeserializer(Money.class, moneyDeserializer);
        // 注册抽象类型MonetaryAmount的序列化/反序列化,委托给Money的处理逻辑
        addSerializer(MonetaryAmount.class, moneySerializer);
        addDeserializer(MonetaryAmount.class, moneyDeserializer);
    }
}

3. 测试类使用自动配置的WebTestClient

删除手动构建WebTestClient的代码,直接注入Spring自动配置的实例,确保使用正确的Jackson配置:

@WebFluxTest( controllers = UserController.class )
@Import( { JacksonConfig.class, FindUserById.class, FindAllUsers.class, AddUserAccount.class, AddUserBeneficiary.class, WebFluxControllerSecurityTestConfig.class } )
class UserControllerTest {
    @Autowired
    UserController controller;

    @Autowired
    private WebTestClient webTestClient;

    @MockBean
    UserRepository repository;

    @MockBean
    JwtTokenFilter filter;

    @Test
    @WithMockUser
    void testGetgetUserById() {
        CurrencyUnit eur = Monetary.getCurrency( "EUR" );

        var user = User.builder()
                .id( "4787889456456456456frfrfrf582" )
                .identityId( "iyioyuy9y98y9y9" )
                .firstName( "firstname2" )
                .lastName( "lastname2" )
                .role( Role.USER )
                .balance( Money.of( 200, eur ) )
                .username( "test2@test.com" ).build();
        when( repository.findById( "4787889456456456456frfrfrf87" ) )
                .thenReturn( Mono.just( user ) );

        webTestClient
                .get().uri( "/api/v1/users/4787889456456456456frfrfrf87" )
                .exchange()
                .expectStatus().isOk()
                .expectBodyList( UserDto.class )
                .hasSize( 1 );
        Mockito.verify( repository, times( 1 ) ).findById( "4787889456456456456frfrfrf87" );
    }
}

额外检查项

  • 确保MoneySerializer也添加了@Component注解,让Spring管理其实例。
  • 确认User或UserDto中的balance字段类型如果是MonetaryAmount,自定义模块已覆盖该抽象类型的处理逻辑。

内容的提问来源于stack exchange,提问作者cyril

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 22:06:13