I am working with a mocked object like the following:
@Mock
private RecipeService recipeService
I also have the following method inside the test class:
@Test
public void testAddRecipeWithNonUniqueName() throws Exception {
Recipe recipe = new Recipe();
doThrow(Exception.class)
.when(recipeService)
.save(recipe);
mockMvc.perform(post("/recipes/add-recipe")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.param("id", "1")
.param("name", "recipe1"))
.andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:/recipes/add"));
}
As you can see, I am using mockito's doThrow
method to decide what exception is going to be thrown when the void
method named save
is called.
I want to make a POST request using a MockMvc
object. So the method marked with the /recipes/add-recipe
endpoint will be called inside one of my controller classes. The following snippet of code shows that method in detail:
@RequestMapping(value = "/recipes/add-recipe", method = RequestMethod.POST)
public String addRecipe(@Valid Recipe recipe, BindingResult result, RedirectAttributes redirectAttributes,
@AuthenticationPrincipal User user){
String response = validateFormValues(recipe, redirectAttributes, result,
"redirect:/recipes/add");
if(!response.isEmpty())return response;
recipe.setUser(user);
try {
recipeService.save(recipe);
}catch(Exception e){
redirectAttributes.addFlashAttribute("uniqueConstraintError",
String.format("The name \"%s\" is already taken by another recipe. " +
"Please try again!",
recipe.getName()));
return "redirect:/recipes/add";
}
setUserForIngredientsAndSteps(recipe);
redirectAttributes.addFlashAttribute("flash",
new FlashMessage("The recipe has been added successfully!", FlashMessage.Status.SUCCESS));
return String.format("redirect:/recipes/%s/detail", recipe.getId());
}
The above method contains a try-catch block. When the recipeService.save()
is called, I am expecting that an exception will be thrown, and handled by the catch block. But that doesn't happen. Instead, the other lines are executed.
What am I missing ?
the doTrhow()
method you are calling is triggered only when you save on the specific recipe you created before.
You need to tell Mockito to throw on any recipe
Mockito.doThrow(Exception.class)
.when(recipeService)
.save(Mockito.any(Recipe.class));
Recipe recipe = new Recipe();
doThrow(Exception.class)
.when(recipeService)
.save(recipe);
This code will only work if the exact same instance of Recipe
is passed to the save method. If you have implemented an equals
and/or hashCode
method passing in a Recipe
instance if the expected values 1
and name
might make it work.
Recipe recipe = new Recipe();
recipe.setId(1);
recipe.setName("name");
doThrow(Exception.class)
.when(recipeService)
.save(recipe);
However as you probably want to test the error situation it is probably easier to always throw an exception. For this use the any()
matcher.
doThrow(Exception.class)
.when(recipeService)
.save(any(Recipe.class);
Now upon calling save, regardless of the passed in Recipe
the exception will be thrown.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.