本文介绍了测试MockBean为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个班级定义

@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;
    }
}

其中的保留是一个简单的Pojo

where Reservation is a simple 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());
    }
}

我收到此错误:

.... ....

.... ....

原因:com.fasterxml.jackson.databind.exc.InvalidDefinitionException:未为类org.mockito.internal.debugging.LocationImpl找到序列化程序,也未找到创建BeanSerializer的属性(为避免异常,请禁用SerializationFeature.FAIL_ON_EMPTY_BEANS)(通过参考链: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 [位置"])

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"])

如何以正确的方式注入预订?

How can I inject reservation in the right way??

谢谢

推荐答案

您会收到此错误,因为当您使用@MockBean(或在非Spring环境中使用@Mock)时,会得到一个Mockito模拟对象.该对象是您对象的空心代理.该代理具有与类相同的公共方法,默认情况下返回其返回类型的默认值(例如,对于对象为null,对于int等为1),或者对于void方法不执行任何操作

You're getting the error because when you use @MockBean (or @Mock in a non Spring environment) you get a Mockito mock object. This object is a hollow proxy of your object.The proxy has the same public methods as your class and by default return the default value of it's return type (e.g. null for objects, 1 for ints, etc.) or does nothing for void methods.

Jackson抱怨,因为它必须序列化没有字段的代理,Jackson不知道该怎么办.

Jackson is complaining because it has to serialize this proxy that has no fields and Jackson does not know what to do.

通常,当您模拟要测试的某个类的依赖项时,您将模拟它是用于测试的类的公共方法.直接返回您的依赖关系在现实世界中不是一个好用例-您不太可能必须编写这样的代码.

In general when you mock a dependency of some class that you want to test, you mock it's public methods, that are used in the class that you test.Directly returning your dependency is not a good real world use case - it's very unlikely that you will have to write a code like this.

我想您正在尝试学习,所以让我提供一个改进的示例:

I guess you're trying to learn so let me provide an improved example:

@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的对象.

Instead of directly injecting a value object you usually have a service class that contain some business logic and return something - in my example ReservationService which have a method getReservation() that return and object of type Reservation.

有了这个,您就可以在测试中模拟ReservationService.

Having that, in your test you can mock the 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());
    }
}

这篇关于测试MockBean为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-29 21:05