Junit Mock повторяет симулированные клиентские вызовы, но только последняя пародия возвращается несколько раз - PullRequest
0 голосов
/ 19 октября 2019

У меня есть приложение Spring Boot, которое использует Feign Client для вызова микросервиса для добавления пользователей в таблицу User при создании нового отдела (новый отдел будет вставлен в таблицу Department). Запрос выглядит так:

Запрос:

 {
  "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);
 }

UserService:

@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,ссс». Я попытался использовать цикл FOR в UserService, а не в потоке, результат был таким же, поэтому это было не из-за потока. Я также попытался удалить цикл FOR в Junit и просто трижды вызвал макет, тот же результат. Я не уверен, что это как-то связано с издевательством над клиентом 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();  
    }

1 Ответ

3 голосов
/ 19 октября 2019

Чтобы метод возвращал разные значения для последующего вызова, вы можете использовать

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
...