繁体   English   中英

Mockito when().thenReturn() 返回 Null 什么时候应该返回空列表

[英]Mockito when().thenReturn() Returning Null when it should return empty list

我一直在试图弄清楚为什么当我有when(controller.findIngredientsByCategory(any()).thenReturn(Collections.emptyList())时,我的模拟 findIngredientsByCategory 方法返回 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);
 }

下面是 controller 的实现:

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

当我告诉它返回一个空列表时,我不确定为什么模拟 controller 会通过这个请求返回 null 。 如果有人可以帮忙,我将不胜感激。 谢谢。

MockMvc实际上将调用由 Spring 测试框架引导和创建的IngredientController控制器,但不会调用您使用@MockBean注释的模拟IngredientController控制器,因此您所做的所有存根都不会被调用。

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

因此,代码应如下所示:

@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 IngredientRepository ingredientRepository;


  @Test
  public void fooTest(){
    when(ingredientRepository.findByCategory(any()).thenReturn(Collections.emptyList())

    //And use the MockMvc to send a request to the controller, 
    //and then assert the returned MvcResult
  }

}

使用new ArrayList()代替Collections.emptyList()

when(controller.findIngredientsByCategory(any()).thenReturn(new ArrayList())

java.util.Collections.emptyList()和新列表(例如new ArrayList<>()之间的核心区别是不变性

Collections.emptyList()返回一个无法修改的列表( java.util.Collections.EmptyList )。

请记住,Collection.emptyList() 只创建一次新的空列表实例。

测试中的请求路径是“/ingredients/filter=meat”,但应该是“/ingredients/filter?category=meat”。 因此,似乎没有调用getIngredientsByCategory

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM