Comment tester si le chemin JSON n’inclut pas un élément spécifique ou si l’élément est présent, il est nul?

J’ai écrit quelques routines simples de tests unitaires pour une application web simple de spring. Lorsque j’ajoute une annotation @JsonIgnore sur une méthode getter d’une ressource, l’object json résultant n’inclut pas l’élément json correspondant. Donc, lorsque ma routine de test unitaire essaie de tester si cette valeur est nulle (ce qui est le comportement attendu pour mon cas, je ne veux pas que le mot de passe soit disponible dans l’object json), la routine de test s’exécute dans une exception:

java.lang.AssertionError: Aucune valeur pour le chemin JSON: $ .password, exception: Aucun résultat pour le chemin: $ [‘password’]

C’est la méthode de test unitaire que j’ai écrite, en testant le champ ‘password’ avec la méthode is (nullValue ()):

@Test public void getUserThatExists() throws Exception { User user = new User(); user.setId(1L); user.setUsername("zobayer"); user.setPassword("123456"); when(userService.getUserById(1L)).thenReturn(user); mockMvc.perform(get("/users/1")) .andExpect(jsonPath("$.username", is(user.getUsername()))) .andExpect(jsonPath("$.password", is(nullValue()))) .andExpect(jsonPath("$.links[*].href", hasItem(endsWith("/users/1")))) .andExpect(status().isOk()) .andDo(print()); } 

Je l’ai aussi essayé avec jsonPath (). Exist () qui obtient une exception similaire indiquant que le chemin n’existe pas. Je partage d’autres extraits de code pour que toute la situation devienne plus lisible.

La méthode du contrôleur que je teste ressemble à ceci:

 @RequestMapping(value="/users/{userId}", method= RequestMethod.GET) public ResponseEntity getUser(@PathVariable Long userId) { logger.info("Request arrived for getUser() with params {}", userId); User user = userService.getUserById(userId); if(user != null) { UserResource userResource = new UserResourceAsm().toResource(user); return new ResponseEntity(userResource, HttpStatus.OK); } else { return new ResponseEntity(HttpStatus.NOT_FOUND); } } 

J’utilise l’assembleur de ressources de hateos de spring pour convertir l’entité en objects de ressources et c’est ma classe de ressources:

 public class UserResource extends ResourceSupport { private Long userId; private Ssortingng username; private Ssortingng password; public Long getUserId() { return userId; } public void setUserId(Long userId) { this.userId = userId; } public Ssortingng getUsername() { return username; } public void setUsername(Ssortingng username) { this.username = username; } @JsonIgnore public Ssortingng getPassword() { return password; } public void setPassword(Ssortingng password) { this.password = password; } } 

Je comprends pourquoi il y a une exception, d’une certaine manière, le test a réussi à ne pas trouver le champ mot de passe. Mais ce que je veux faire, c’est d’exécuter ce test pour vérifier que le champ n’est pas présent ou, s’il est présent, qu’il contient une valeur nulle. Comment puis-je atteindre cet objective?

Il y a un article similaire dans le débordement de stack: Hamcrest avec MockMvc: vérifiez que la clé existe mais que la valeur peut être nulle

Dans mon cas, le champ peut également être inexistant.

Pour mémoire, ce sont les versions des packages de test que j’utilise:

   com.fasterxml.jackson.core jackson-core 2.6.1   com.fasterxml.jackson.core jackson-annotations 2.6.1   com.fasterxml.jackson.core jackson-databind 2.6.1   com.jayway.jsonpath json-path 2.0.0 test   com.jayway.jsonpath json-path-assert 2.0.0 test   junit junit 4.12 test   org.mockito mockito-all 1.10.19 test  

Merci d’avance.

[EDIT] Pour être plus précis, disons que vous devez écrire un test pour une entité où vous savez que certains champs doivent être nuls ou vides ou ne doivent même pas exister, et que vous ne parcourez pas le code pour voir S’il y a un JsonIgnore ajouté en haut de la propriété. Et vous voulez que vos tests réussissent, comment puis-je le faire?

S’il vous plaît n’hésitez pas à me dire que ce n’est pas du tout pratique, mais serait toujours agréable de savoir.

[EDIT] Le test ci-dessus réussit avec les anciennes dépendances json-path suivantes:

   com.jayway.jsonpath json-path 0.9.1 test   com.jayway.jsonpath json-path-assert 0.9.1 test  

[EDIT] J’ai trouvé un correctif qui fonctionne avec la dernière version de jayway.jasonpath après avoir lu la documentation de json path matcher de Spring.

 .andExpect(jsonPath("$.password").doesNotExist()) 

J’ai eu le même problème avec la nouvelle version. Il me semble que la fonction doesNotExist () vérifiera que la clé n’est pas dans le résultat:

 .andExpect(jsonPath("$.password").doesNotExist()) 

@JsonIgnore se comporte comme prévu, ne produit pas le mot de passe dans la sortie json, alors comment pouvez-vous espérer tester quelque chose que vous excluez explicitement de la sortie?

La ligne:

 .andExpect(jsonPath("$.property", is("some value"))); 

ou même un test que la propriété est null:

 .andExpect(jsonPath("$.property").value(IsNull.nullValue())); 

correspond à un json comme:

 { ... "property": "some value", ... } 

où la partie importante est le côté gauche, c’est l’existence de “propriété”:

Au lieu de cela, @JsonIgnore ne produit pas la propriété dans la sortie, vous ne pouvez donc pas vous attendre à ce que ce soit dans le test ou dans la sortie de production. Si vous ne voulez pas que la propriété soit dans la sortie, c’est bien, mais vous ne pouvez pas vous attendre à la tester. Si vous voulez qu’il soit vide dans la sortie (à la fois dans prod et test), vous voulez créer une méthode Mapper statique au milieu qui ne transmet pas la valeur de la propriété à l’object json:

 Mapper.mapPersonToRest(User user) {//exclude the password} 

et alors votre méthode serait:

 @RequestMapping(value="/users/{userId}", method= RequestMethod.GET) public ResponseEntity getUser(@PathVariable Long userId) { logger.info("Request arrived for getUser() with params {}", userId); User user = Mapper.mapPersonToRest(userService.getUserById(userId)); if(user != null) { UserResource userResource = new UserResourceAsm().toResource(user); return new ResponseEntity<>(userResource, HttpStatus.OK); } else { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } } 

Si vous souhaitez que Mapper.mapPersonToRest renvoie un utilisateur avec un mot de passe nul, vous pouvez écrire un test unitaire normal sur cette méthode.

PS Bien sûr, le mot de passe est crypté sur la firebase database, non? 😉