Тестирование MockBean Null

У меня есть определение этого класса

@RestController
public class ReservationController {
    @Autowired
    private Reservation reservation;

    @RequestMapping(value = "/reservation", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.POST)
    @ResponseBody
    public Reservation getReservation() {

        return reservation;
    }
}

где Reservation - это простой Pojo

public class Reservation {
    private long id;
    private String reservationName;

    public Reservation() {
        super();
        this.id = 333;
        this.reservationName = "prova123";
    }

    public Reservation(long id, String reservationName) {
        super();
        this.id = id;
        this.reservationName = reservationName;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getReservationName() {
        return reservationName;
    }

    public void setReservationName(String reservationName) {
        this.reservationName = reservationName;
    }

    @Override
    public String toString() {
        return "Reservation [id = " + id + ", reservationName = " + reservationName + "]";
    }
}

когда я пытаюсь протестировать этот класс

@WebMvcTest
@RunWith(SpringRunner.class)
public class MvcTest {
    @Autowired
    private MockMvc mockMvc;

    @MockBean(name = "reservation")
    private Reservation reservation;

    @Test
    public void postReservation() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.post("/reservation"))
                .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
                .andExpect(MockMvcResultMatchers.status().isOk());
    }
}

У меня такая ошибка:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.mockito.internal.debugging.LocationImpl]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.mockito.internal.debugging.LocationImpl and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: spring.boot.usingSpringBoot.entity.Reservation$MockitoMock$980801978["mockitoInterceptor"]->org.mockito.internal.creation.bytebuddy.MockMethodInterceptor["mockHandler"]->org.mockito.internal.handler.InvocationNotifierHandler["invocationContainer"]->org.mockito.internal.stubbing.InvocationContainerImpl["invocationForStubbing"]->org.mockito.internal.invocation.InvocationMatcher["invocation"]->org.mockito.internal.invocation.InterceptedInvocation["location"])

.... ....

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.mockito.internal.debugging.LocationImpl and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: spring.boot.usingSpringBoot.entity.Reservation$MockitoMock$980801978["mockitoInterceptor"]->org.mockito.internal.creation.bytebuddy.MockMethodInterceptor["mockHandler"]->org.mockito.internal.handler.InvocationNotifierHandler["invocationContainer"]->org.mockito.internal.stubbing.InvocationContainerImpl["invocationForStubbing"]->org.mockito.internal.invocation.InvocationMatcher["invocation"]->org.mockito.internal.invocation.InterceptedInvocation["location"])

Как правильно ввести резервирование?

Спасибо

Прежде всего, ваш класс резервирования - это простое pojo, поэтому он не охвачен контекстом Spring, это означает, что вам может потребоваться создать класс резервирования servie, который должен быть аннотирован с помощью Service (или компонента). И в вашем тестовом классе, если вы хотите издеваться над своим код, который вы используете InjectMock

TinyOS 14.12.2018 16:10

да, ты прав ... я забыл @Component to Reservation Class

dargui 17.12.2018 09:19
4
2
14 920
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы получаете сообщение об ошибке, потому что, когда вы используете @MockBean (или @Mock в среде, отличной от Spring), вы получаете mock-объект Mockito. Этот объект является пустым прокси-сервером вашего объекта. Прокси-сервер имеет те же общедоступные методы, что и ваш класс, и по умолчанию возвращает значение по умолчанию для его возвращаемого типа (например, null для объектов, 1 для int и т. д.) Или ничего не делает для void-методов .

Джексон жалуется, потому что он должен сериализовать этот прокси, у которого нет полей, и Джексон не знает, что делать.

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.mockito.internal.debugging.LocationImpl and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS

В общем, когда вы имитируете зависимость некоторого класса, который хотите протестировать, вы имитируете его общедоступные методы, которые используются в тестируемом классе. Непосредственный возврат вашей зависимости - не лучший вариант использования в реальном мире - очень маловероятно, что вам придется писать такой код.

Думаю, вы пытаетесь учиться, поэтому позвольте мне привести улучшенный пример:

@RestController
public class ReservationController {
    @Autowired
    private ReservationService reservationService;     //my chnage here

    @RequestMapping(value = "/reservation", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, method = RequestMethod.POST)
    @ResponseBody
    public Reservation getReservation() {

        return reservationService.getReservation();   //my chnage here
    }
}

Вместо прямого внедрения объекта значения у вас обычно есть класс обслуживания, который содержит некоторую бизнес-логику и что-то возвращает - в моем примере ReservationService, у которого есть метод getReservation(), который возвращает, и объект типа Reservation.

Имея это, в своем тесте вы можете издеваться над ReservationService.

@WebMvcTest
@RunWith(SpringRunner.class)
public class MvcTest {
    @Autowired
    private MockMvc mockMvc;

    @MockBean(name = "reservation")
    private ReservationService reservationService;    //my chnage here

    @Test
    public void postReservation() throws Exception {
        // You need that to specify what should your mock return when getReservation() is called. Without it you will get null
        when(reservationService.getReservation()).thenReturn(new Reservation()); //my chnage here

        mockMvc.perform(MockMvcRequestBuilders.post("/reservation"))
                .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
                .andExpect(MockMvcResultMatchers.status().isOk());
    }
}

Большое спасибо ... Я собираюсь использовать эту структуру для своего кода.

dargui 17.12.2018 09:15

Просто для удовольствия от обсуждения ... Я также пробовал использовать этот подход, и он работает. В методе @Test я сначала устанавливаю зависимость BookingController.setReservation (new Reservation (100, "name1"));

dargui 17.12.2018 09:28

Другие вопросы по теме