首页 > 解决方案 > 如何测试具有多个返回的函数?

问题描述

我目前正在学习java,并且正在制作一个电子商务网站。我目前正在编写一些测试。我的问题是,我的控制器中的一个映射会根据名为 results 的列表的长度返回不同的页面。这是一个搜索项目功能,如果项目不存在,它会将您带回搜索项目页面,如果有一个具有该名称的项目,它将带您到另一个页面,如果该项目有多个实例,它会返回您到第三页。映射如下。

@RequestMapping("/findItemByName")
    public String processFindForm(Item item, BindingResult result, Map<String, Object> model) {
        // allow parameterless GET request for /products to return all records
        if (item.getItemName() == null) {
            item.setItemName(""); // empty string signifies broadest possible search
        }

        // find products by name
        List<Item> results = itemRepo.findByItemName(item.getItemName());
        if (results.isEmpty()) {
            // no products found
            result.rejectValue("name", "notFound", "not found");
            return "finditem";
        } else if (results.size() == 1) {
            // 1 product found
            item = results.iterator().next();
            model.put("item", item);
            return "showitem";
        } else {
            // multiple products found
            model.put("items", results);
            return "showitems";
        }

    }

无论我似乎在做什么,我都只能在测试时让函数返回“finditem”。到目前为止,我在课堂上将此作为我的代码进行测试。

@Mock
    Model model;
    @Mock
    Item item;
    @Mock
    Item item2;
    @Mock
    ItemRepository itemRepo;
    @Mock
    Map<String,Object> mockMap;
    @Mock
    BindingResult mockResult;
    @Mock
    List<Item> results;
    
    @InjectMocks

@Test
    public void testFindByItemNameReturnsFindItemWhenListLengthOne() {
        
        results.add(item);
        String expectedValue = "showitem";
        String actualValue = itemController.processFindForm(item, mockResult, mockMap);
        
        Assert.assertEquals(expectedValue, actualValue);
    }
    
    @Test
    public void testFindByItemNameReturnsFindItemWhenListLengthTwo() {
        List<Item> results = new ArrayList<>();
        
        results.add(item2);
        results.add(item2);
        System.out.print(results.size());
        String expectedValue = "showitems";
        String actualValue = itemController.processFindForm(item, mockResult, mockMap);
        
        Assert.assertEquals(expectedValue, actualValue);
    }

如何将结果“注入”(如果这是正确的词)到函数中以更改我的实际值?

提前致谢

标签: javajunitmockito

解决方案


如果你想单独测试你ItemController的,我建议模拟它对ItemRepositoy. 如何执行此操作取决于您要编写集成测试还是单元测试。

我个人更喜欢使用集成测试来测试控制器。Spring Boot 提供了@WebMvcTestAnnotation,它在您的测试中禁用了全自动配置,而是仅配置 Web 层所需的组件。

你的测试看起来像这样:

@WebMvcTest
class ItemControllerTest {

    @MockBean
    private ItemRepository itemRepository;

    @Autowired
    private MockMvc mockMvc;

    @Test
    void cleverTestName() throws Exception {
        // mock behaviour of itemRepository
        doReturn(Collections.emptyList()).when(itemRepository).findByItemName(anyString());

        //make request to the controller and check results
        mockMvc.perform(...)
                .andExpect(...);
    }
}

使用此设置,您可以编写测试来检查您的响应。有关更多信息,@WebMvcTest我会建议我自己的一篇关于该主题的博客文章 :)


推荐阅读