Je suis en train d'écrire des tests d'intégration pour une application Web de printemps et j'ai atteint une étape où j'ai besoin de simuler des appels de méthodes de service qui ont un type de retour avide. J'ai fait des recherches sur certains moyens de le faire, mais aucun ne semble être la bonne façon.
Ce que je veux faire est: p>
ci-dessous, je vais fournir le code et les deux façons principales que j'ai déjà essayées. Si quelqu'un peut aider ce serait génial! P>
la méthode qui nécessite de se moquer de fort> p> le service qui a besoin Appelant (Méthode de sauvegarde) FORT> P> @RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@WebAppConfiguration
public class RecipeControllerTests {
private MockMvc mockMvc;
@Mock
private RecipeService recipeService;
@Mock
private UserService userService;
@Mock
private IngredientService ingredientService;
@Autowired
WebApplicationContext wac;
@InjectMocks
private RecipeController recipeController;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.webAppContextSetup(wac).apply(springSecurity()).build();
}
/**
* Tests for index pages / & /recipes
*/
@Test
@WithUserDetails(value = "daniel")
public void indexPageLoads() throws Exception {
List<Recipe> recipes = recipeListBuilder();
List<Ingredient> ingredients = ingredientsListBuilder();
when(recipeService.findAll()).thenReturn(recipes);
when(ingredientService.findAll()).thenReturn(ingredients);
when(userService.findByUsername("daniel")).thenReturn(userBuilder());
mockMvc.perform(get("/recipes"))
.andExpect(model().attributeExists("recipes", "ingredients", "favs"))
.andExpect(status().isOk());
}
/**
* Tests for page /recipes/add
*/
@Test
@WithMockUser
public void addRecipePageLoads() throws Exception {
mockMvc.perform(get("/recipes/add"))
.andExpect(model().attributeExists("task", "buttonAction", "action", "photo", "recipe"))
.andExpect(status().isOk());
}
@Test
@WithUserDetails("daniel")
public void createNewRecipeRedirects() throws Exception {
User user = userBuilder();
Recipe recipe = recipeBuilder(1L);
recipe.setOwner(user);
user.addFavorite(recipe);
MultipartFile photo = new MockMultipartFile("image", "food.jpeg",
"image/jpeg", "dummy content file".getBytes());
when(userService.findByUsername("daniel")).thenReturn(user);
verify(recipeService, times(1)).save(recipe, photo);
verify(userService, times(1)).save(user);
mockMvc.perform(post("/recipes/add"))
.andExpect(redirectedUrl("/recipes"))
.andExpect(flash().attributeExists("flash"));
}
private User userBuilder() {
User user = new User();
user.setFavorites(recipeListBuilder());
user.setId(1L);
user.setRoles(new String[]{"ROLE_USER", "ROLE_ADMIN"});
user.setUsername("daniel");
user.setPassword("password");
return user;
}
private List<Recipe> recipeListBuilder() {
List<Recipe> recipes = new ArrayList<>();
recipes.add(recipeBuilder(1L));
recipes.add(recipeBuilder(2L));
return recipes;
}
private List<Ingredient> ingredientsListBuilder() {
List<Ingredient> ingredients = new ArrayList<>();
ingredients.add(ingredientBuilder());
return ingredients;
}
private Ingredient ingredientBuilder() {
Ingredient ingredient = new Ingredient();
ingredient.setCondition("good");
ingredient.setName("test ing");
ingredient.setQuantity(1);
ingredient.setId(1L);
return ingredient;
}
private Recipe recipeBuilder(Long id) {
Recipe recipe = new Recipe();
recipe.setName("Test recipe");
recipe.setDescription("Test Description");
recipe.setId(id);
recipe.setCategory(Category.ALL_CATEGORIES);
recipe.setCookTime(10);
recipe.setPrepTime(10);
recipe.addIngredient(ingredientBuilder());
return recipe;
}
}
3 Réponses :
Si vous avez une logique que vous souhaitez tester un appareil à tester et que cette logique invoque des méthodes d'autre composant que vous souhaitez simuler et certaines de ces méthodes renvoient void code> - la manière typique de tester votre logique est Pour vérifier que votre logique a effectivement appelé les méthodes code> Void code> d'objet moquée. Vous pouvez y parvenir en utilisant
Mockito :: Vérifier CODE>:
Mockito.verify(recipeService, Mockito.times(1)).save(any(Recipe.class), any(MultipartFile.class));
Si vous moquez la méthode de sauvegarde, j'utiliserais l'un des "do ..." Docs Bien sûr, cela suggère que votre méthode a un effet secondaire quelque part. p>
Si vous souhaitez vous assurer qu'une méthode est appelée, vous pouvez utiliser «Vérifier» comme mentionné dans d'autres réponses. p>
Généralement moqueur vous permet de remplacer une certaine collaboration / fonctionnalité avec une version sous le contrôle des tests où la vérification permet de vérifier quelque chose survenu (ou non) p>
Essayez Mockito.Donothing () Code>: Il dit essentiellement à Mockito de ne rien faire lorsqu'un procédé d'un objet simulé est appelé:
Si vous avez une méthode qui retourne
void code> et que vous souhaitez vous moquer de l'objet de la classe qui possède cette méthode, la manière typique de le faire est de vérifier que cette méthode a été appelée à un objet simulé en utilisant
Mockito :: Vérifiez code>.
En outre, vous n'avez rien dit de ce que vous attendez-vous et ce qui se passe à la place.
Désolé, je devrais être plus explicite. Je veux vous moquer de la sauvegarde de l'appel de service () qui prend un objet de recette et un multipartfile.
Il suffit d'utiliser
Mockito :: Vérifier code> Pour tester si votre logique appelée
Enregistrer la méthode sur votre moce car vous ne voulez probablement pas tester la logique d'économie ici.
Je viens d'essayer cela et j'ai reçu l'erreur suivante: "Je voulais mais non invoqué: recipesservice.save (com.danielturato.recipe.recipe.recipe@1f1574c, org.springframework.mock.web.mockmultipartfile@16c9e378); -> com.danielturato.recipe.recipe.RecipecontrollertestS.Createn EwreciperDirects (RE CIPECONTROLERTESS. JAVA: 112) En fait, il y avait des interactions nulle avec ce simulacre. "
Cela signifie que votre logique n'a pas invoqué la méthode. Probablement
résultat.haserrors () code> retourné true.
Ou que la logique appelée sauvegarde () sur une autre instance de recettes. Montrez-nous votre test complet, mais minimal.
Je vais ajouter mon code de test maintenant
Vous devez appeler
Mockito :: Vérifier Code> Après le
MockMVC.Perform () CODE> ... Vous souhaitez tester que la logique de traitement de votre demande a été invoquée sur votre moce.
Mockito :: Vérifier CODE> est utilisé pour affirmer, non pour configurer des simulacres.
Voilà. Vous utilisez un test d'intégration B> Spring, où le ressort crée un service et des contrôleurs réels et commence un contexte d'application Web réel. Donc, le contrôleur et les services qu'il utilise n'ont rien à voir avec les services de simulation et le contrôleur que vous créez vous-même dans le test à l'aide du Mockito
@mock code> et
@InjectMocks code> annotations . Vous devez utiliser le
@mockbean code> des annotations de printemps pour indiquer le ressort de créer une fusion de service de service, injecter dans le contrôleur et dans votre test.
Même lorsque je mets la vérification () en dessous de la zone PEFORM (), je reçois cette erreur voulue mais non invoquée. Aussi, que voulez-vous dire par @Mockbean Annotation et où je le mettrai-je
docs.spring.io/spring-boot/docs/current/reeference/htmlsingle / ...