Mockito 使用不同的集合参数模拟相同的方法调用

Mockito mock same method calls with different collection-arguments

我尝试使用不同的集合参数模拟相同的方法调用。

我的问题是我没有从 Mocked-Call 获得正确的模拟答案作为输入。

测试-Class:

@ExtendWith(SpringExtension.class)
public class CollectionTest {

    @MockBean
    private Controller c;
    
    @BeforeEach
    public void init() {
        Collection<String> a = Mockito.anyCollection();
        a.add("a");
        Mockito.when(c.run(a)).thenReturn("a");
        
        Collection<String> b = Mockito.anyCollection();
        b.add("b");
        Mockito.when(c.run(b)).thenReturn("b");
    }

    @Test
    public void test() {
        assertEquals("a", c.run(Lists.newArrayList("a"))); // DOESNT'WORK!!! Returns "b" but should "a"
        assertEquals("b", c.run(Lists.newArrayList("b"))); // 
    }
}

控制器-Class:

@Service
public class Controller{
    public String run(Collection<String> c) {
        return "not-mocked";
    }   
}

我不知道为什么它不 return “a”。我试图将集合更改为字符串,但行为相同。

获得以下行为的步骤是什么?

@Test
public void test() {
    assertEquals("a", c.run(Lists.newArrayList("a"))); // should return "a"
    assertEquals("b", c.run(Lists.newArrayList("b"))); // should return "b"
}

我正在使用 Java Mockito“3.1”和 Spring,但我认为 Mockito 是这里的重要信息。

编写两个测试将显示您期望的结果。 您正在向同一个控制器添加两个不同的结果,因此您只会得到最后一个结果:Mockito.when(c.run(b)).thenReturn("b"); 普通的。您的 setUp() 中最后模拟的预期结果将保留在内存中。

之前的回答是: 您可以使用 junit 和 mockito 之类的东西来测试您的 spring-web-mvc 应用程序。 看起来像这样:

@WebMvcTest(controllers = UserController.class)
@ActiveProfiles("test")
class UserControllerTest {
   
    @Autowired                           
    private MockMvc mockMvc;  
                                                 
    @MockBean                           
    private UserService userService; 
                                               
    private List<User> userList;       
                                            
    @BeforeEach                           
    void setUp() {                               
       this.userList = new ArrayList<>();
       this.userList.add(new User(1L, "user1@gmail.com", "pwd1","User1"));
       this.userList.add(new User(2L, "user2@gmail.com", "pwd2","User2"));
       this.userList.add(new User(3L, "user3@gmail.com", "pwd3","User3"));                                                       
    }
}

举个例子:

@Test
void shouldFetchAllUsers() throws Exception {
    given(userService.findAllUsers()).willReturn(userList);
    this.mockMvc.perform(get("/api/users"))
        .andExpect(status().isOk())
        .andExpect(jsonPath("$.size()", is(userList.size() )));
}

示例来自@see https://medium.com/backend-habit/integrate-junit-and-mockito-unit-testing-for-controller-layer-91bb4099c2a5

你的第二个电话 - Mockito.when(c.run(b)).thenReturn("b"); 否决了我们的第一次调用,因此 Mockito 将始终 return “b”。 如果您需要来自同一个电话的多个答案,您可以使用 varags 变体:

when(c.run(anyCollection())).thenReturn("a", "b");

现在第一次调用控制器的 运行 方法将 return“a”,所有后续调用将 return“b”。您可以提供任意多的 return 个结果,最后一个将作为答案重复。