Java Mockito when().thenReturn()在应返回空列表时返回Null

Java Mockito when().thenReturn()在应返回空列表时返回Null,java,spring,unit-testing,mockito,spring-mvc-test,Java,Spring,Unit Testing,Mockito,Spring Mvc Test,我一直在试图弄清楚为什么我的模拟findIngredientsByCategory方法在我有when(controller.findIngredientsByCategory(any()).thenReturn(Collections.emptyList())时返回null。此实现适用于findAll方法 下面是我的单元测试实现: @RunWith(SpringJUnit4ClassRunner.class) @WebMvcTest(IngredientController.class) @Co

我一直在试图弄清楚为什么我的模拟findIngredientsByCategory方法在我有
when(controller.findIngredientsByCategory(any()).thenReturn(Collections.emptyList())
时返回null。此实现适用于findAll方法

下面是我的单元测试实现:

@RunWith(SpringJUnit4ClassRunner.class)
@WebMvcTest(IngredientController.class)
@ContextConfiguration(classes = {TestContext.class, WebApplicationContext.class})
@WebAppConfiguration
public class IngredientControllerTest {

  @Autowired
  private WebApplicationContext context;

  @Autowired
  private MockMvc mvc;

  @MockBean
  private IngredientController ingredientController;

  @Before
  public void setup() {
    MockitoAnnotations.initMocks(this);
    mvc = MockMvcBuilders.webAppContextSetup(context).build();
  }

  @Autowired
  private ObjectMapper mapper;

  private static class Behavior {
    IngredientController ingredientController;

    public static Behavior set(IngredientController ingredientController) {
      Behavior behavior = new Behavior();
      behavior.ingredientController = ingredientController;
      return behavior;
    }

    public Behavior hasNoIngredients() {
      when(ingredientController.getAllIngredients()).thenReturn(Collections.emptyList());
      when(ingredientController.getIngredientsByCategory(any())).thenReturn(Collections.emptyList());
      when(ingredientController.getIngredientById(anyString())).thenReturn(Optional.empty());
      return this;
    }
  }

  @Test
  public void getIngredientsByCategoryNoIngredients() throws Exception {
    Behavior.set(ingredientController).hasNoIngredients();
    MvcResult result = mvc.perform(get("/ingredients/filter=meat"))
        .andExpect(status().isOk())
        .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
        .andReturn();
    String content = result.getResponse().getContentAsString();
    System.out.println(content);
 }
以下是控制器的实现:

@RestController
@RequestMapping("/ingredients")
public class IngredientController {

  @Autowired
  private IngredientRepository repository;

  @RequestMapping(value = "/filter", method = RequestMethod.GET)
  public List getIngredientsByCategory(@RequestParam("category") String category) {
    return repository.findByCategory(category);
  }
}

当我告诉模拟控制器返回一个空列表时,我不知道为什么模拟控制器会在这个请求中返回null。如果有人能帮助我,我将不胜感激!谢谢。

模拟MVC实际上会调用由Spring测试框架引导和创建的
IngreditController
,但是不要调用您用
@MockBean
注释的模拟
IngredientController
,因此不会调用您所做的所有存根

实际上,
@WebMvcTest
的目的是测试
@RestController
及其相关的Spring配置是否正确,因此需要创建
IngredientController
的真实实例,而不是使用模拟实例。相反,您应该模拟
IngredientController
中的依赖项(即
IngredEnterpository

因此,代码应该如下所示:

@RunWith(SpringJUnit4ClassRunner.class)
@WebMvcTest(IngreditController.class)
@ContextConfiguration(类={TestContext.class,WebApplicationContext.class})
@WebAppConfiguration
公共类InCreditControllerTest{
@自动连线
私有WebApplicationContext上下文;
@自动连线
私有MockMvc;
@蚕豆
私人储蓄存款存款存款存款存款存款存款存款存款存款存款;
@试验
公共空间{
当(IngredEnterpository.findByCategory(any())。然后返回(Collections.emptyList())
//并使用MockMvc向控制器发送请求,
//然后断言返回的MvcResult
}
}

测试中的第个请求路径是“/配料/过滤器=肉”,但它应该是“/配料/过滤器?类别=肉”。因此,似乎没有调用
getIngredientsByCategory

是的!这解决了问题。谢谢!真不敢相信我错过了。p.S.无论如何,正如@ken chan提到的,这对控制器来说是一种奇怪的方式。是的,我现在看到了。谢谢大家。你如何用这个实现实例化控制器?
SpringJUnit4ClassRunner
will启动spring上下文,然后在封面下创建控制器。就像您正常启动spring应用程序一样,您不需要自己创建控制器。这对学习模拟的工作原理非常有帮助,所以谢谢!