测试MockBean为空

时间:2018-12-14 13:23:29

标签: spring spring-boot testing mockito

我有这个班级定义

@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

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:请求处理失败;嵌套的异常是org.springframework.http.converter.HttpMessageConversionException:类型定义错误:[简单类型,类org.mockito.internal.debugging.LocationImpl];嵌套的异常是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 [” location“] )

     

...   ....

     

原因: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 [“位置”])

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

谢谢

1 个答案:

答案 0 :(得分:1)

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

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

  

com.fasterxml.jackson.databind.exc.InvalidDefinitionException:否   找到类org.mockito.internal.debugging.LocationImpl的序列化器   并没有发现创建BeanSerializer的属性(避免   例外,请禁用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中,该类具有一个返回类型为{{ 1}}。

有了这个,您就可以在测试中模拟getReservation()

Reservation