Необходимо смоделировать метод службы в конечной точке POST, пропуская аннотацию @RequestBody - PullRequest
0 голосов
/ 05 апреля 2019

Я пытаюсь написать модульный тест для конечной точки POST REST. Мне нужно смоделировать сервисный метод, который использует вышеупомянутую конечную точку, используя mockito. Использование mock mvc для запуска конечной точки.

Я издеваюсь над userService.saveUser (user), использующим в конечной точке, и возвращаю целое число как созданный userId. Но похоже, что mock всегда возвращает 0 вместо 7777 (userId определен). Для «проверки» написано «Аргумент (ы) разные!» который передается userService (user) в конечной точке и в макете, который я определил.

Ошибка подтверждения Mockito:

Argument(s) are different! Wanted:
userService.saveUser(
    com.foo.dto.User@741f8dbe
);
-> at com.foo.controller.UserControllerTest.saveUser(UserControllerTest.java:104)
Actual invocation has different arguments:
userService.saveUser(
    com.foo.dto.User@212dfd39
);
-> at com.foo.controller.UserController.saveUser(UserController.java:45)

Comparison Failure:  <Click to see difference>

Полагаю, это происходит потому, что аннотация @RequestBody создает совершенно новый объект User. Это вызывает проблему неработающего макета "userService". (Поправьте меня, если я ошибаюсь)

Может быть, мне нужно обойти эту проблему, чтобы запустить конечную точку и передать объект "user" в "userService", как это определено в классе Test, и пропустить аннотацию @RequestBody.

Может ли кто-нибудь помочь мне пройти через это? любая помощь будет высоко ценится.

Конечная точка:

@PostMapping("/users")
public ResponseEntity<String> saveUser(@RequestBody User user){

    int userId = userService.saveUser(user);

    return new ResponseEntity<>("User created. Id: "+ userId, HttpStatus.CREATED);
}

Тестовый класс:

@RunWith(SpringJUnit4ClassRunner.class)
public class UserControllerTest {
    @InjectMocks
    private UserController userController;
    @Mock
    private UserService userService;
    private ObjectMapper mapper;
    private MockMvc mockMvc;
    private Integer userId = 7777;

    @Before
    public void setUp() throws Exception{
        MockitoAnnotations.initMocks(this);
        this.mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
        mapper = new ObjectMapper();

        user = new User();
        user.setName("DummyUser");
    }

    @Test
    public void saveUser(){
        when(userService.saveUser(user)).thenReturn(userId);
        this.mockMvc.perform(post("/users")
                .accept(MediaType.TEXT_PLAIN)
                .contentType(MediaType.APPLICATION_JSON)
                .content(mapper.writeValueAsString(user)))
                .andExpect(status().isCreated())
                .andExpect(content()
                       .contentTypeCompatibleWith(MediaType.TEXT_PLAIN))
                .andExpect(content().string("User created. Id: "+userId));
        verify(userService).saveUser(user);
    }

}

1 Ответ

1 голос
/ 05 апреля 2019

Я думаю, что причина в том, что вы сказали.То, что вы могли бы сделать, это использовать средство сравнения, чтобы перейти к макету, чтобы он возвращал то, что вы хотите, при условии, что он получает объект определенного типа (вместо определенного объекта:

import static org.mockito.ArgumentMatchers.any;
...
when(userService.saveUser(any(User.class))).thenReturn(userId);

Макет, используемый так, как вы его используете, будет возвращать то, что вы хотите, только если он получает в качестве параметра вызова конкретный объект, который вы передаете при выполнении when. Как вы можете видеть из имеющегося исключения,mock ожидает получить объект со ссылкой com.foo.dto.User@741f8dbe (который вы создаете в своем методе setUp), но он получает com.foo.dto.User@212dfd39, который генерируется Джексоном, когда он десериализует тело вызова rest.

...