Junit Mock 重复假装客户端调用,但只有最后一个 Mock 多次返回
Junit Mock Repeated Feign Client Calls but Only the Last Mock Returned Multiple Times
我有一个 Spring 启动应用程序,它使用 Feign Client 调用微服务以在创建新部门时将用户添加到用户 table(新部门将被插入部门 table).请求看起来像:
要求:
{
"department": "math",
"usernameList": ["aaa", "bbb", "ccc"]
}
用户模型:
public class User {
private String username;
}
Feign 客户端:
import org.springframework.cloud.openfeign.FeignClient;
@FeignClient(name = "user-client", url = "/.../user", configuration = UserConfiguration.class)
public interface UserClient {
@RequestMapping(method = RequestMethod.POST, value = "users")
User createUser(User user);
}
用户服务:
@Service
public class UserService {
private final UserClient userClient;
public UserResponse createUser(@Valid Request request);
List<User> userList = request.getUsernameList()
.stream()
.map(username -> userClient.createUser(mapToUser(username))
.collect(Collectors.toList());
......
}
以上代码有效,我能够将 3 个用户添加到数据库中。 userList 有 3 个正确的用户名。但是,当我 运行 下面的 junit 测试时,似乎只有最后一个 userResp ("ccc") 作为模拟响应返回了 3 次。当我在调试模式下 运行 junit 测试时,我看到每次 thenReturn(userResp) 都有正确的 userResp,但在 UserService 中,userList 最终包含 3 "ccc",而不是一个列表"aaa, bbb, ccc"。我尝试在 UserService 中使用 FOR 循环而不是流,结果是一样的,所以不是因为流。我还尝试删除 Junit 中的 FOR 循环,只调用模拟 3 次,结果相同。我不确定这是否与 Feign 客户端模拟有关,或者我是否在测试用例中做错了什么。有人可以帮忙吗?
我的 Junit:
public class UserTest {
@MockBean
private UserClient userClient;
@Test
public void testAddUser() throws Exception {
for (int i=1; i<=3; i++) {
User userResp = new User();
if (i==1) {
userResp.setUsername("aaa");
// mock response
Mockito.when(userClient.createUser(ArgumentMatchers.any(User.class)))
.thenReturn(userResp);
}
if (i==2) {
userResp.setUsername("bbb");
// mock response
Mockito.when(userClient.createUser(ArgumentMatchers.any(User.class)))
.thenReturn(userResp);
}
if (i==3) {
userResp.setUsername("ccc");
// mock response
Mockito.when(userClient.createUser(ArgumentMatchers.any(User.class)))
.thenReturn(userResp);
}
}
// invoke the real url
MvcResult result = mockMvc.perform(post("/users")
.content(TestUtils.toJson(userRequest, false))
.contentType(contentType))
.andDo(print())
.andExpect(status().isCreated())
.andReturn();
}
要使方法 return 为后续调用设置不同的值,您可以使用
Mockito.when(userClient.createUser(ArgumentMatchers.any(User.class)))
.thenReturn("aaa")
.thenReturn("bbb")
.thenReturn("ccc"); //any
// Or a bit shorter with varargs:
Mockito.when(userClient.createUser(ArgumentMatchers.any(User.class)))
.thenReturn("aaa", "bbb", "ccc"); //any
我有一个 Spring 启动应用程序,它使用 Feign Client 调用微服务以在创建新部门时将用户添加到用户 table(新部门将被插入部门 table).请求看起来像:
要求:
{
"department": "math",
"usernameList": ["aaa", "bbb", "ccc"]
}
用户模型:
public class User {
private String username;
}
Feign 客户端:
import org.springframework.cloud.openfeign.FeignClient;
@FeignClient(name = "user-client", url = "/.../user", configuration = UserConfiguration.class)
public interface UserClient {
@RequestMapping(method = RequestMethod.POST, value = "users")
User createUser(User user);
}
用户服务:
@Service
public class UserService {
private final UserClient userClient;
public UserResponse createUser(@Valid Request request);
List<User> userList = request.getUsernameList()
.stream()
.map(username -> userClient.createUser(mapToUser(username))
.collect(Collectors.toList());
......
}
以上代码有效,我能够将 3 个用户添加到数据库中。 userList 有 3 个正确的用户名。但是,当我 运行 下面的 junit 测试时,似乎只有最后一个 userResp ("ccc") 作为模拟响应返回了 3 次。当我在调试模式下 运行 junit 测试时,我看到每次 thenReturn(userResp) 都有正确的 userResp,但在 UserService 中,userList 最终包含 3 "ccc",而不是一个列表"aaa, bbb, ccc"。我尝试在 UserService 中使用 FOR 循环而不是流,结果是一样的,所以不是因为流。我还尝试删除 Junit 中的 FOR 循环,只调用模拟 3 次,结果相同。我不确定这是否与 Feign 客户端模拟有关,或者我是否在测试用例中做错了什么。有人可以帮忙吗?
我的 Junit:
public class UserTest {
@MockBean
private UserClient userClient;
@Test
public void testAddUser() throws Exception {
for (int i=1; i<=3; i++) {
User userResp = new User();
if (i==1) {
userResp.setUsername("aaa");
// mock response
Mockito.when(userClient.createUser(ArgumentMatchers.any(User.class)))
.thenReturn(userResp);
}
if (i==2) {
userResp.setUsername("bbb");
// mock response
Mockito.when(userClient.createUser(ArgumentMatchers.any(User.class)))
.thenReturn(userResp);
}
if (i==3) {
userResp.setUsername("ccc");
// mock response
Mockito.when(userClient.createUser(ArgumentMatchers.any(User.class)))
.thenReturn(userResp);
}
}
// invoke the real url
MvcResult result = mockMvc.perform(post("/users")
.content(TestUtils.toJson(userRequest, false))
.contentType(contentType))
.andDo(print())
.andExpect(status().isCreated())
.andReturn();
}
要使方法 return 为后续调用设置不同的值,您可以使用
Mockito.when(userClient.createUser(ArgumentMatchers.any(User.class)))
.thenReturn("aaa")
.thenReturn("bbb")
.thenReturn("ccc"); //any
// Or a bit shorter with varargs:
Mockito.when(userClient.createUser(ArgumentMatchers.any(User.class)))
.thenReturn("aaa", "bbb", "ccc"); //any