#java #unit-testing #mockito #mockmvc
#java #модульное тестирование #mockito #mockmvc
Вопрос:
Я не смог найти ни одного сообщения, связанного с моей проблемой. Я использую Mockito и хочу протестировать поведение внутри контроллера. Я думаю, что суть проблемы заключается в том, что я неправильно использую Mockito, когда отправляю два аргумента в поддельный интерфейс. Это работает нормально, если я отправляю только один аргумент. Я не думаю, что тот факт, что я также использую Spring mock mvc, имеет к этому какое-то отношение.
У меня есть интерфейс MyService
:
public MyObject doSomeDoggyStuff(long id, SomeOtherObject soo);
Цель интерфейса — выполнить что-то и вернуть MyObject, если он прошел успешно. Если он не может найти объект, просто верните null.
У меня есть контроллер MyController
:
@RestController
@RequestMapping(value = "/dogs")
public MyController
<snip>
@RequestMapping(method = RequestMethod.POST, value = "/{id}/toys/{toy}")
ResponseEntity<MyObject> doDoggyStuff(@PathVariable Long id, @RequestBody Toy toy) {
MyObject result = this.myService.doSomeDoggyStuff(id, toy);
if(result == null) {
return new ResponseEntity("errorinfo", HttpStatus.NOT_FOUND);
}
else {
return new ResponseEntity<MyObject>(result,HttpStatus.CREATED)'
}
}
Мой тестовый класс выглядит так:
Public MyControllerTest <snip>
@Mock
private MyService myServiceMock;
@InjectMocks
private MyController myController;
Соответствующая логика метода тестирования выглядит следующим образом.
MyObject myObj = new MyObject();
Toy toy = new Toy();
when(myServiceMock.doSomeDoggyStuff(1, toy)).thenReturn(myObj);
mockMvc
.perform(
post("/dogs/{id}/toys/{toys}", 1, toy).contentType(
TestUtil.APPLICATION_JSON_UTF8).content(
TestUtil.convertObjectToJsonBytes(toy))).andExpect(status().isCreated())
.andReturn();
Проблема, с которой я сталкиваюсь, заключается в том, что в этом сценарии я ожидаю, что когда он проверяет MyController, который в строке: MyObject result = this.myService.doSomeDoggyStuff(id, toy);
результатом должен быть myObj, который я установил в thenReturn, но он всегда имеет значение null. У меня есть другие методы в моем сервисе, которые принимают только один аргумент, и он работает нормально. Я не могу понять, что мне нужно сделать по-другому, когда я отправляю два аргумента с помощью Mockito.
Комментарии:
1. Вы пытались отладить то, что передается в вызов метода service на самом деле? Это может быть отсутствие реализации equals в классе Toy. Можете ли вы опубликовать код класса Toy?
Ответ №1:
Если я правильно понимаю ваши требования, вы должны использовать макет следующим образом:
when(myServiceMock.doSomeDoggyStuff(eq(1), any(Toy.class))).thenReturn(myObj);
То, как вы написали свой код, макет будет возвращаться myObj
только при вызове Toy
объекта, с помощью которого вы создали его экземпляр, чего никогда не бывает, поскольку Spring создаст экземпляр класса самостоятельно. Проблема не имеет ничего общего с количеством аргументов.
Однако, если вы хотите протестировать конкретный Toy
, а не просто любой его экземпляр, вам нужно будет добавить equals
(и, чтобы быть корректным со спецификацией, a hashCode
) метод, чтобы mockito мог сопоставить игрушки. В отсутствие какого-либо метода equals ссылки проверяются, и, конечно, они не равны, потому что экземпляры не совпадают.
Комментарии:
1. Таким образом, тест не проверяет то, что хотел протестировать Магнус — он пройдет для любого игрушечного объекта. Я считаю, что проблема связана с отсутствием реализации equals в Toy.
2. @macias Вы вполне можете быть правы! Вот почему я добавил первое предложение :). Я соответствующим образом обновлю ответ
3. Спасибо вам обоим! Это прекрасно работает. Mockito — это круто, но иногда немного запутанно корректировать синтаксис для определенных сценариев.
Ответ №2:
Вам нужно либо реализовать equals в вашей игрушке, либо использовать ArgumentCaptor для проверки деталей переданного объекта. В противном случае (как уже упоминалось geoand) вы сравниваете ссылки.