Junit测试失败:HttpMessageConversion错误
Posted
技术标签:
【中文标题】Junit测试失败:HttpMessageConversion错误【英文标题】:Junit test failure: HttpMessageConversion error 【发布时间】:2021-08-27 08:16:25 【问题描述】:我正在尝试使用Mockito
为休息网址编写JUnit
测试用例。
@Override
public void sendWebhook(WebRequest webRequest)
ResponseEntity<Object> webresponse = restService.sendWebhook(webRequest);
restServiceImpl
@Override
public ResponseEntity<Object> sendWebhook(WebRequest webRequest)
ResponseEntity<Object> response = null;
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<webRequest> request = new HttpEntity<>(webRequest, headers);
try
response = restTemplate.exchange(webRequest.getUrl(), HttpMethod.POST, request, Object.class);
catch (ResourceAccessException resourceAccessException)
return null;
return response;
上面的类使用Mockito
的单元测试用例
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class WebServiceImplTest
@Autowired
private RestTemplate restTemplate;
private MockRestServiceServer mockServer;
@Autowired
private RestService restService;
@Before
public void setUp()
MockitoAnnotations.initMocks(this);
mockServer = MockRestServiceServer.createServer(restTemplate);
@Test
public void testSendWebhookWithSuccess() throws Exception
/* setup mock */
WebRequest webRequest = mock(WebRequest.class);
Mockito.when(restService.sendWebhook(webRequest))
.thenReturn(new ResponseEntity<Object>(HttpStatus.OK));
UriComponents uriComponents =
UriComponentsBuilder.fromUriString("http://localhost:8080/mockWeb/sendSuccessMsg").build();
mockServer.expect(requestTo(uriComponents.toUriString())).andExpect(method(HttpMethod.POST))
.andRespond(withSuccess("Success", MediaType.APPLICATION_JSON));
mockServer.verify();
当我运行上面的测试用例时,我得到了,
Results :
Tests in error:
testSendWebhookWithSuccess » HttpMessageConversion
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0
我遇到错误
Mockito.when(restService.sendWebhook(webRequest))
.thenReturn(new ResponseEntity<Object>(HttpStatus.OK));
为什么我会遇到错误。我能知道我错过了什么吗
stackTrace 下面附上
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 38.087 sec <<< FAILURE! - in ...web.service.impl.WebServiceImplTest
testSendWebhookWithSuccess(...service.impl.WebServiceImplTest) Time elapsed: 0.321 sec <<< ERROR!
org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.mockito.internal.invocation.mockref.MockWeakReference]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.mockito.internal.invocation.mockref.MockWeakReference and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.equifax.mortgage.udm.webhook.model.WebRequest$MockitoMock$1970556850["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["mockRef"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1277)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:33)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:755)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:755)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:755)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:755)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:755)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:755)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1516)
at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:1006)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:343)
at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:104)
at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:943)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:737)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:674)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:583)
at ...web.service.impl.RestServiceImpl.sendWebhook(RestServiceImpl.java:50)
【问题讨论】:
将错误堆栈跟踪附加到问题 @Alex 附加堆栈跟踪 据我所知,您正在尝试使用模拟对象调用真实服务。所以RestTemplate
无法序列化它。此外,您还试图在真实服务Mockito.when(restService.sendWebhook(webRequest))
上模拟方法执行
除了上面的评论:当你想用你的 RestTemplate 发送它时,spring 正在尝试用一个 HttpMessageConverter 转换你的 webrequest。这通常是为了让您可以传入对象,例如将它们转换为 json。是否可以使用普通的 pojo 而不是 WebRequest 作为方法参数?
【参考方案1】:
这意味着您的模拟对象正在通过正确的杰克逊反序列化,而您只能对真实对象执行此操作。
在您的情况下,我认为问题出在new ResponseEntity<Object>(...)
:它不是真正的可序列化对象。
为您的 thenReturn(thisBetterBeSerializable)
创建一些具体的东西,因为它显然在嵌套服务调用中的某个地方通过 jackson。
当我在 spring 控制器测试中创建一个模拟对象作为响应时,我得到了确切的异常(“没有为类 org.mockito.internal.invocation.mockref.MockWeakReference 和...找到序列化程序”):
我有这个(意译)
@MockBean
private MyService myService;
@Test
public void test_200Returned() throws Exception
MyRealResponseType mockResponse = Mockito.mock(MyRealResponseType.class); // WRONG!
when(myService.myMethod(any(MyRequest.class))).thenReturn(mockResponse);
this.mockMvc.perform(post("/my/service/api")).andExpect(status().isOk());
一切正常,直到我的控制器类(服务于 /my/service/api 的控制器类)在调用 myService.myMethod
后尝试返回一个对象以获取它。 mockResponse 对象被返回(按计划),但 Jackson 无法处理它。
我解决了我的问题,将我的 Mockito.mock
行替换为:
MyRealResponseType mockResponse = new MyRealResponseType(); // RIGHT!
mockResponse.setSomeNeededPropertyJustInCase("someValue");
...
然后一切正常,我的测试通过了。
你的情况略有不同,但我怀疑如果你创建一个真实的对象来传递给thenReturn
,你的问题就会消失。
【讨论】:
以上是关于Junit测试失败:HttpMessageConversion错误的主要内容,如果未能解决你的问题,请参考以下文章
Selenium 可以截取 JUnit 测试失败的屏幕截图吗?
运行 Junit 测试用例时“加载 ApplicationContext 失败”