Spring 测试MockBean Null
我有这个类定义Spring 测试MockBean Null,spring,spring-boot,testing,mockito,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)
@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.debuging.LocationImpl];嵌套异常为com.fasterxml.jackson.databind.exc.InvalidDefinitionException:找不到类org.mockito.internal.debuging.LocationImpl的序列化程序,也找不到创建BeanSerializer的属性(为避免异常,请禁用SerializationFeature.FAIL\u ON\u EMPTY\u bean)(通过引用链:spring.boot.usingSpringBoot.entity.Reservation$MockitoMock$980801978[“mockitoInterceptor”]->org.mockito.internal.creation.bytebuddy.MockMethodInterceptor[“mockHandler”]->org.mockito.internal.stubing.InvocationContainerImpl[“InvocationForStubing”]->org.mockito.internal.invocation.InvocationMatcher[“invocation”]->org.mockito.internal.invocation.InterceptedInvocation[“location”])
。。。。
原因:com.fasterxml.jackson.databind.exc.InvalidDefinitionException:找不到类org.mockito.internal.debuging.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.stubing.InvocationContainerHandler[“invocationContainer”]->.org.mockito.internal.Stubing.InvocationContainerImpl[)InvocationForStubing“]->org.mockito.internal.invocation.InvocationMatcher[“invocation”]->org.mockito.internal.invocation.InterceptedInvocation[“location”])
如何以正确的方式注入预订
谢谢您收到了错误,因为当您在非Spring环境中使用
@MockBean
(或@Mock
)时,您得到了一个Mockito Mock对象。此对象是您对象的空心代理。该代理与您的类具有相同的公共方法,默认情况下返回其返回类型的默认值(例如,对象为null,int为1等)或对void方法不执行任何操作
Jackson抱怨,因为它必须序列化这个没有字段的代理,Jackson不知道该怎么做
com.fasterxml.jackson.databind.exc.InvalidDefinitionException:否
找到类org.mockito.internal.debuging.LocationImpl的序列化程序
并且没有发现创建BeanSerializer的属性(以避免
异常,在\u空\u bean上禁用SerializationFeature.FAIL\u
通常,当您模拟要测试的某个类的依赖项时,您会模拟它的公共方法,这些方法在您测试的类中使用。
直接返回依赖项并不是一个好的实际用例——您不太可能必须编写这样的代码
我猜您正在尝试学习,所以让我提供一个改进的示例:
@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());
}
}
首先,您的reservation类是一个简单的pojo,所以它不在spring上下文中,这意味着您可能需要创建一个服务预订类,该类必须用服务(或组件)注释在你的测试类中,如果你想模拟你的代码,你使用InjectMockyes是的,你是对的……我忘记了@Component to Reservation类非常感谢……我将在我的代码中使用这种结构。只是为了讨论的乐趣……我也尝试过使用这种方法,它是有效的。在@test方法中,我首先设置了依赖项setReservation(新预订(100,“名称1”);