java - 无法在使用 RestResponsePage 的测试中构造“org.springframework.data.domain.Pageable”的实例
问题描述
我已经从 Spring Boot 1.5.11.RELEASE 迁移到 Spring Boot 2.3.6.RELEASE。我的测试没有通过。我有的:
我的测试
@Autowired
protected TestRestTemplate restTemplate;
@Test
public void getParamWithValueAndPaging() {
String uri = "?page=1&size=2";
ResponseEntity<RestResponsePage<OperationDto>> operationsResponse =
restTemplate.exchange(URI + uri,
HttpMethod.GET, TestUtils.HTTP_OPERATOR,
new ParameterizedTypeReference<RestResponsePage<OperationDto>>() {
});
assertEquals(2, operationsResponse.getBody().getNumberOfElements());
assertEquals(1, operationsResponse.getBody().getNumber());
}
休息响应页面
package *;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import java.util.ArrayList;
import java.util.List;
@Getter
@Setter
public class RestResponsePage<T> extends PageImpl<T> {
private int number;
private int size;
private int totalPages;
private int numberOfElements;
private long totalElements;
private boolean previousPage;
private boolean first;
private boolean nextPage;
private boolean last;
private List<T> content;
private Sort sort;
public RestResponsePage(List<T> content, Pageable pageable, long total) {
super(content, pageable, total);
}
public RestResponsePage(List<T> content) {
super(content);
}
public RestResponsePage() {
super(new ArrayList<T>());
}
public PageImpl<T> pageImpl() {
return new PageImpl<T>(getContent(), PageRequest.of(getNumber(),
getSize(), getSort()), getTotalElements());
}
}
API接口
@Api("**")
@RequestMapping("/*/*/operation")
public interface OperationResource<Domain> {
@ApiOperation("*")
@GetMapping
@ApiResponses({
@ApiResponse(code = 200, message = "")
})
GenericPageSpringSupport<OperationDto> getUserOperation(@Spec(path = "", spec = Equal.class) Specification<Domain> specification, Pageable pageable);
APIImpl
@Override
public GenericPageSpringSupport<OperationDto> getUserOperation(
@Conjunction(value = {
@Or({@Spec(path = "id", spec = LikeIgnoreCase.class, params = "id"),
@Spec(path = "name", spec = LikeIgnoreCase.class, params = "name")})
}, and = @Spec(path = "operationType", spec = Equal.class, params = "type")) Specification<UserOperation> specification, Pageable pageable) {
return service.getUserOperation(specification, pageable);
}
GenericPageSpringSupport(它是适配器,它以两种格式返回数据:Page 和 GenericPage)
public class GenericPageSpringSupport<T> extends GenericPage<T> {
@JsonUnwrapped
private final Page<T> page;
public GenericPageSpringSupport(Page<T> page) {
super(page.getContent(), page.getTotalElements());
this.page = page;
}
public List<T> getContent() {
return page.getContent();
}
public long getTotalElements() {
return page.getTotalElements();
}
}
最后,我在测试中的错误:
org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.springframework.data.domain.Pageable]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `org.springframework.data.domain.Pageable` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: (PushbackInputStream); line: 1, column: 467] (through reference chain: my.package.RestResponsePage["pageable"])
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:282)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:243)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:105)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:996)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:979)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:739)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:672)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:610)
at org.springframework.boot.test.web.client.TestRestTemplate.exchange(TestRestTemplate.java:781)
at my.package.tests.testClass.getOperationWithPaging(TestClass.java:866)
at my.package.tests.testClass.getParamWithValueAndPaging(TestClass.java:165)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:132)
at org.testng.internal.MethodInvocationHelper$1.runTestMethod(MethodInvocationHelper.java:238)
at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.run(AbstractTestNGSpringContextTests.java:181)
at org.testng.internal.MethodInvocationHelper.invokeHookable(MethodInvocationHelper.java:252)
at org.testng.internal.TestInvoker.invokeMethod(TestInvoker.java:595)
at org.testng.internal.TestInvoker.invokeTestMethod(TestInvoker.java:174)
at org.testng.internal.MethodRunner.runInSequence(MethodRunner.java:46)
at org.testng.internal.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:822)
at org.testng.internal.TestInvoker.invokeTestMethods(TestInvoker.java:147)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:146)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:128)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at org.testng.TestRunner.privateRun(TestRunner.java:764)
at org.testng.TestRunner.run(TestRunner.java:585)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:384)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:378)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:337)
at org.testng.SuiteRunner.run(SuiteRunner.java:286)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1218)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1140)
at org.testng.TestNG.runSuites(TestNG.java:1069)
at org.testng.TestNG.run(TestNG.java:1037)
at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66)
at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:109)
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `org.springframework.data.domain.Pageable` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: (PushbackInputStream); line: 1, column: 467] (through reference chain: my.package.RestResponsePage["pageable"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1615)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1077)
at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:265)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:371)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:164)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4526)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3521)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:274)
... 40 more
在阅读了有关此问题的一些主题后,我尝试像这样更改 RestResponsePage 类:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import java.util.ArrayList;
import java.util.List;
@JsonIgnoreProperties(ignoreUnknown = true)
public class RestResponsePage<T> extends PageImpl<T> {
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
public RestResponsePage(
@JsonProperty("content") List<T> content,
@JsonProperty("number") int number,
@JsonProperty("size") int size,
@JsonProperty("totalElements") Long totalElements,
@JsonProperty("pageable") JsonNode pageable,
@JsonProperty("last") boolean last,
@JsonProperty("totalPages") int totalPages,
@JsonProperty("sort") JsonNode sort,
@JsonProperty("first") boolean first,
@JsonProperty("numberOfElements") int numberOfElements) {
super(content, PageRequest.of(number, size), totalElements);
}
public RestResponsePage(
List<T> content,
Pageable pageable,
long total) {
super(content, pageable, total);
}
public RestResponsePage(List<T> content) {
super(content);
}
public RestResponsePage() {
super(new ArrayList<T>());
}
}
之后我的问题是:
org.springframework.web.client.UnknownContentTypeException: Could not extract response: no suitable HttpMessageConverter found for response type [my.package.RestResponsePage<my.package.OperationDto>] and content type [application/json]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:126)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:996)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:979)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:739)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:672)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:610)
at org.springframework.boot.test.web.client.TestRestTemplate.exchange(TestRestTemplate.java:781)
at my.package.tests.TestClass.getOperationWithPaging(TestClass.java:866)
at my.package.tests.TestClass.getParamWithValueAndPaging(TestClass.java:165)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:132)
at org.testng.internal.MethodInvocationHelper$1.runTestMethod(MethodInvocationHelper.java:238)
at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.run(AbstractTestNGSpringContextTests.java:181)
at org.testng.internal.MethodInvocationHelper.invokeHookable(MethodInvocationHelper.java:252)
at org.testng.internal.TestInvoker.invokeMethod(TestInvoker.java:595)
at org.testng.internal.TestInvoker.invokeTestMethod(TestInvoker.java:174)
at org.testng.internal.MethodRunner.runInSequence(MethodRunner.java:46)
at org.testng.internal.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:822)
at org.testng.internal.TestInvoker.invokeTestMethods(TestInvoker.java:147)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:146)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:128)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
at org.testng.TestRunner.privateRun(TestRunner.java:764)
at org.testng.TestRunner.run(TestRunner.java:585)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:384)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:378)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:337)
at org.testng.SuiteRunner.run(SuiteRunner.java:286)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1218)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1140)
at org.testng.TestNG.runSuites(TestNG.java:1069)
at org.testng.TestNG.run(TestNG.java:1037)
at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66)
at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:109)
我该如何解决?
解决方案
推荐阅读
- qt - 如何在 Qt Creator 中将 Qdialog 设置为具有尽可能小的固定高度和扩展宽度?
- java - 为什么对象数组中的元素没有更新?
- python - 使用 facecolor 而非 edgecolor 将标签添加到线框图
- python - what is XLA_GPU and XLA_CPU for tensorflow
- android - 如何制作透明的 GLSurfaceView
- google-cloud-platform - GCP 负载平衡器中基于路径的配置
- wordpress - 将外部页面的链接添加到 wordpress 博客菜单。
- string - Lua: string of specific length
- botframework - Microsoft bot 框架 v3 网络聊天频道不适用于 ngrok
- scala - 我如何组成多个单子?IO / Future,甚至可能带有状态和选项