I have an application in webflux and SpringBoot 3.2
i have custom Jackson Module and serializer, ubfortunately when i try to execute test no serializer found
Custom module
package ae.company.banking.configuration.converters;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new MoneyModule());
objectMapper.registerModule(new JavaTimeModule());
return objectMapper;
}
}
DeSerializer
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import javax.money.CurrencyUnit;
import javax.money.Monetary;
import org.javamoney.moneta.Money;
import org.springframework.stereotype.Component;
@Component
public class MoneyDeserializer extends JsonDeserializer<Money> {
@Override
public Money deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
JsonNode node = p.getCodec().readTree(p);
double amount = node.get("amount").asDouble();
String currencyCode = node.get("currency").asText();
CurrencyUnit currency = Monetary.getCurrency(currencyCode);
return Money.of(amount, currency);
}
}
The module
package ae.company.banking.configuration.converters;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.javamoney.moneta.Money;
public class MoneyModule extends SimpleModule {
public MoneyModule() {
addSerializer( Money.class, new MoneySerializer());
addDeserializer( Money.class, new MoneyDeserializer());
}
}
my test
@WebFluxTest( controllers = UserController.class )
@Import( { JacksonConfig.class, FindUserById.class, FindAllUsers.class, AddUserAccount.class, AddUserBeneficiary.class, WebFluxControllerSecurityTestConfig.class } )
class UserControllerTest {
@Autowired
UserController controller;
@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( "[email protected]" ).build();
when( repository.findById( "4787889456456456456frfrfrf87" ) )
.thenReturn( Mono.just( user ) );
var testClient = WebTestClient.bindToController( controller ).webFilter( new SecurityContextServerWebExchangeWebFilter() )
.apply( springSecurity() )
.build();
testClient
.get().uri( "/api/v1/users/4787889456456456456frfrfrf87" )
.exchange()
.expectStatus().isOk()
.expectBodyList( UserDto.class )
.hasSize( 1 );
Mockito.verify( repository, times( 1 ) ).findById( "4787889456456456456frfrfrf87" );
}
And the error
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of javax.money.MonetaryAmount
(no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
To make it work ive done this
var testClient = WebTestClient
and injected mapper
@Autowired ObjectMapper mapper;
i will try the solution of @M. Deinum