Après avoir effectué la mise à niveau vers la nouvelle version 2.2.0.RELEASE
De Spring Boot, certains de mes tests ont échoué. Il semble que le MediaType.APPLICATION_JSON_UTF8
A été déprécié et n'est plus renvoyé comme type de contenu par défaut à partir des méthodes du contrôleur qui ne spécifient pas le type de contenu explicitement.
Code de test comme
String content = mockMvc.perform(get("/some-api")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andReturn()
.getResponse()
.getContentAsString();
n'a soudainement plus fonctionné car le type de contenu n'était pas compatible comme indiqué ci-dessous
Java.lang.AssertionError: Content type
Expected :application/json;charset=UTF-8
Actual :application/json
Changer le code en .andExpect(content().contentType(MediaType.APPLICATION_JSON))
a résolu le problème pour l'instant.
Mais maintenant, lors de la comparaison de content
à l'objet sérialisé attendu, il y a toujours un décalage s'il y a des caractères spéciaux dans l'objet. Il semble que la méthode .getContentAsString()
n'utilise pas le codage de caractères UTF-8 par défaut (plus).
Java.lang.AssertionError: Response content expected:<[{"description":"Er hörte leise Schritte hinter sich."}]> but was:<[{"description":"Er hörte leise Schritte hinter sich."}]>
Expected :[{"description":"Er hörte leise Schritte hinter sich."}]
Actual :[{"description":"Er hörte leise Schritte hinter sich."}]
Comment puis-je obtenir content
en encodage UTF-8?
Oui. C'est un problème de 2.2.0 spring-boot. Ils définissent la dépréciation pour le codage par défaut du jeu de caractères.
.getContentAsString(StandardCharsets.UTF_8)
- bonne mais dans toute réponse serait remplie ISO 8859-1 par défaut.
Dans mon projet, j'ai mis à jour le convertisseur créé actuellement:
@Configuration
public class SpringConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.stream()
.filter(converter -> converter instanceof MappingJackson2HttpMessageConverter)
.findFirst()
.ifPresent(converter -> ((MappingJackson2HttpMessageConverter) converter).setDefaultCharset(UTF_8));
}
...
L'utilisation de .getContentAsString(StandardCharsets.UTF_8)
au lieu de .getContentAsString()
résout le problème.
Le caractère d'encodage par défaut n'est plus UTF-8 depuis la version 5.2.0 de spring.
Pour continuer à utiliser UTF-8, vous devez le définir dans la ServletResponse du résultat MockMvc. Pour définir le codage de caractères par défaut sur UTF-8, faites quelque chose comme ceci dans votre méthode de configuration:
@Before
public void setUp() {
mockMvc = webAppContextSetup(wac).addFilter(((request, response, chain) -> {
response.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
})).build();
}
Ensuite, vous pouvez utiliser l'instance mockMvc pour effectuer votre demande.
J'espère que cette aide.
Paramètre supplémentaire à MockMvc, .accept(MediaType.APPLICATION_JSON_UTF8_VALUE)
:
String content = mockMvc.perform(get("/some-api")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andReturn()
.getResponse()
.getContentAsString();
Ce problème n'est pas Spring Boot, mais spécifique à MockMvc, je suppose. Par conséquent, une solution de contournement doit être appliquée à MockMvc uniquement. ( JSON doit être encodé en UTF-8 .)
problème connexe: Mauvaise gestion UTF-8 dans MockMvc pour la réponse JSON · Numéro # 23622 · spring-projects/spring-framework
Selon this pull request des développeurs de printemps, l'en-tête UTF-8 n'est plus requis et est donc obsolète. Si vous utilisez l'en-tête UTF-8 dans votre application, vous pouvez envisager de le supprimer de votre application au lieu d'essayer de corriger votre test. Assurez-vous simplement que vous utilisez l'en-tête Content-Type: application/json et ça devrait aller.
J'utilise Spring Boot 1.5.15.RELEASE et j'ai rencontré le même problème lors de l'écriture de tests.
La première solution qui m'a aidé a été d'ajouter .characterEncoding ("UTF-8")) comme ceci:
String content = mockMvc.perform(get("/some-api")
.contentType(MediaType.APPLICATION_JSON)
.characterEncoding("UTF-8"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andReturn()
.getResponse()
.getContentAsString();
J'utilise un StandaloneMockMvcBuilder dans ma classe de test, donc la deuxième solution qui m'a aidé était de créer un filtre, par exemple:
private static class Utf8Filter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
filterChain.doFilter(request, response);
}
}
et l'ajouter plus tard à la méthode standaloneSetup dans ma classe de test comme ceci:
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
final SomeResource someResource = new SomeResource(someService);
this.restLankMockMvc = MockMvcBuilders.standaloneSetup(someResource)
.setCustomArgumentResolvers(pageableArgumentResolver)
.setControllerAdvice(exceptionTranslator)
.setConversionService(createFormattingConversionService())
.setMessageConverters(jacksonMessageConverter)
.addFilter(new Utf8Filter())
.build();
}