SpringBoot 3.2 WebFlux测试中自定义Jackson序列化器未生效问题
解决方案:SpringBoot 3.2 WebFlux测试中自定义Jackson MoneyModule不生效问题
问题根源
@WebFluxTest环境下,Spring Boot会自动配置WebFlux专属的Jackson组件,直接注册ObjectMapperBean不会被WebTestClient识别,必须通过Jackson2ObjectMapperBuilderCustomizer来定制全局Jackson配置。- 自定义
MoneyModule中手动实例化序列化器/反序列化器,未利用Spring依赖注入,导致实例脱离Spring上下文管理。 - 错误提示指向抽象类
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
相关产品推荐
相关产品推荐

