使用Mockito的doThrow方法时不会抛出异常

问题描述 投票:0回答:2

我正在使用如下的模拟对象:

@Mock
private RecipeService recipeService

我在测试类中也有以下方法:

    @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"));
    }

正如你所看到的,我正在使用mockito的doThrow方法来决定在调用名为voidsave方法时抛出什么异常。

我想使用MockMvc对象发出POST请求。因此,使用/recipes/add-recipe端点标记的方法将在我的一个控制器类中调用。以下代码片段详细显示了该方法:

    @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());
    }

上面的方法包含try-catch块。当调用recipeService.save()时,我期望抛出异常,并由catch块处理。但这不会发生。而是执行其他行。

我错过了什么?

java spring testing junit mockito
2个回答
1
投票
Recipe recipe = new Recipe();

doThrow(Exception.class)
        .when(recipeService)
        .save(recipe);

只有将完全相同的Recipe实例传递给save方法时,此代码才有效。如果你已经实现了equals和/或hashCode方法传入Recipe实例,如果预期值1name可能使它工作。

Recipe recipe = new Recipe();
recipe.setId(1);
recipe.setName("name");

doThrow(Exception.class)
        .when(recipeService)
        .save(recipe);

但是,由于您可能希望测试错误情况,因此始终抛出异常可能更容易。为此使用any()匹配器。

doThrow(Exception.class)
        .when(recipeService)
        .save(any(Recipe.class);

现在调用save时,无论传入Recipe,都会抛出异常。


2
投票

只有当您保存之前创建的特定配方时,才会触发您调用的doTrhow()方法。

你需要告诉Mockito投入任何食谱

Mockito.doThrow(Exception.class)
            .when(recipeService)
            .save(Mockito.any(Recipe.class));
© www.soinside.com 2019 - 2024. All rights reserved.