【发布时间】:2020-10-06 05:54:05
【问题描述】:
我正在尝试在 Spring Boot 中测试一个 Reactive Controller,但是即使接收到的字节流正常,我也无法反序列化返回的对象,如下代码所示...
@Test
public void testListTemp(@Autowired HypermediaWebTestClientConfigurer configurer) {
Page<T> page = new PageImpl<T>(Arrays.asList(getEntity()), PageRequest.of(0, 7), 1);
when(getRepository().findAll(any(SearchQuery.class), any(Pageable.class))).thenReturn(Mono.just(page));
//@formatter:off
WebTestClient
.bindToController(getController())
.argumentResolvers((argsConfigurer) -> {
Integer MAX_PAGE_SIZE = 100;
ReactivePageableHandlerMethodArgumentResolver pageableResolver = new ReactivePageableHandlerMethodArgumentResolver();
pageableResolver.setMaxPageSize(MAX_PAGE_SIZE);
pageableResolver.setFallbackPageable(SearchQuery.getDefaultPageable());
argsConfigurer.addCustomResolver(pageableResolver);
}).build()
.mutateWith(configurer)
.get()
.uri(getBaseUri()+"/")
.accept(MediaTypes.HAL_JSON)
.exchange()
.expectBody(String.class)
.consumeWith(result -> {
String model = result.getResponseBody();
System.err.println("model: " + model);
});
//@formatter:on
}
... 型号:
{
"links":[
{
"rel":"self",
"href":"/test/exampleRoot/example/?includedDeleted=false&langCode=en-US&page=0&size=7",
"title":"Misma página"
},
{
"rel":"first",
"href":"/test/exampleRoot/example/?includedDeleted=false&langCode=en-US&page=0&size=7",
"title":"Primera página"
},
{
"rel":"prev",
"href":"/test/exampleRoot/example/?includedDeleted=false&langCode=en-US&page=0&size=7",
"title":"Página previa"
},
{
"rel":"next",
"href":"/test/exampleRoot/example/?includedDeleted=false&langCode=en-US&page=0&size=7",
"title":"Siguiente página"
},
{
"rel":"last",
"href":"/test/exampleRoot/example/?includedDeleted=false&langCode=en-US&page=0&size=7",
"title":"Última página"
},
{
"rel":"page-1",
"href":"/test/exampleRoot/example/?includedDeleted=false&langCode=en-US&page=0&size=7",
"title":"1"
},
{
"rel":"create",
"href":"/test/exampleRoot/example/?langCode=en-US"
}
],
"content": [
{
"createdBy":null,
"createdDate":null,
"lastModifiedBy":null,
"lastModifiedDate":null,
"deletedBy":null,
"deletedDate":null,
"businessId":2,
"field01":"FieldE2_01",
"field02":2,
"links":[
{
"rel":"self",
"href":"/test/exampleRoot/example/2?langCode=en-US&includeDeleted=false"
},
{
"rel":"all",
"href":"/test/exampleRoot/example/"
},
{
"rel":"delete",
"href":"/test/exampleRoot/example/2"
},
{
"rel":"update",
"href":"/test/exampleRoot/example/2?langCode=en-US"
}]
}],
"page":
{
"size":7,
"totalElements":1,
"totalPages":1,
"number":0
}
}
但在以下代码中不起作用:
@Test
public void testListTemp(@Autowired HypermediaWebTestClientConfigurer configurer) {
Page<T> page = new PageImpl<T>(Arrays.asList(getEntity()), PageRequest.of(0, 7), 1);
when(getRepository().findAll(any(SearchQuery.class), any(Pageable.class))).thenReturn(Mono.just(page));
WebTestClient
.bindToController(getController())
.argumentResolvers((argsConfigurer) -> {
Integer MAX_PAGE_SIZE = 100;
ReactivePageableHandlerMethodArgumentResolver pageableResolver = new ReactivePageableHandlerMethodArgumentResolver();
pageableResolver.setMaxPageSize(MAX_PAGE_SIZE);
pageableResolver.setFallbackPageable(SearchQuery.getDefaultPageable());
argsConfigurer.addCustomResolver(pageableResolver);
}).build()
.mutateWith(configurer)
.get()
.uri(getBaseUri()+"/")
.accept(MediaTypes.HAL_JSON)
.exchange()
.expectBody(new TypeReferences.PagedModelType<ExampleDto>() {})
.consumeWith(result -> {
PagedModel<ExampleDto> model = result.getResponseBody();
System.err.println("model: " + model);
});
//@formatter:on
}
返回的对象在哪里:
PagedResource { content: [], metadata: Metadata { number: 0, total pages: 1, total elements: 1, size: 7 }, links: }
所以没有内容和链接被反序列化。
至于您的信息,这里有 ExampleDto 类和层次结构的根
package net.crezco.api.example;
import javax.validation.constraints.Positive;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import net.crezco.api.CzcDto;
@Getter
@Setter
@NoArgsConstructor
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
public class ExampleDto extends CzcDto<ExampleDto> {
@Size(max = 20)
private String field01;
@Positive
private Integer field02;
}
以及层次结构的根:
package net.crezco.api;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.persistence.Transient;
import javax.validation.constraints.Null;
import javax.validation.constraints.Positive;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.hateoas.RepresentationModel;
import org.springframework.util.ReflectionUtils;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import net.crezco.validation.onCreate;
import net.crezco.validation.onUpdate;
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class CzcDto<T extends RepresentationModel<? extends T>> extends RepresentationModel<T> {
@Transient
@JsonIgnore
private final List<String> reserved = Arrays.asList("reserved", "id", "version", "createdBy", "createdDate", "lastModifiedBy", "lastModifiedDate", "deletedBy", "deletedDate", "_log");
/**
* Created by
*/
@JsonProperty
private String createdBy;
/**
* Created date
*/
@JsonProperty
private Date createdDate;
/**
* Last modified by
*/
@JsonProperty
private String lastModifiedBy;
/**
* Last modified date
*/
@JsonProperty
private Date lastModifiedDate;
/**
* Deleted by
*/
@JsonProperty
private String deletedBy;
/**
* Deleted date
*/
@JsonProperty
private Date deletedDate;
/**
* ID of the entity
*/
@Null(groups = onCreate.class)
@Positive(groups = onUpdate.class)
@JsonProperty
private Long businessId;
public CzcDto() {
super();
}
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Date getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
public String getLastModifiedBy() {
return lastModifiedBy;
}
public void setLastModifiedBy(String lastModifiedBy) {
this.lastModifiedBy = lastModifiedBy;
}
public Date getLastModifiedDate() {
return lastModifiedDate;
}
public void setLastModifiedDate(Date lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
}
public String getDeletedBy() {
return deletedBy;
}
public void setDeletedBy(String deletedBy) {
this.deletedBy = deletedBy;
}
public Date getDeletedDate() {
return deletedDate;
}
public void setDeletedDate(Date deletedDate) {
this.deletedDate = deletedDate;
}
public Long getBusinessId() {
return businessId;
}
public void setBusinessId(Long businessId) {
this.businessId = businessId;
}
/************************************
*
* UTILITY NETHODS
*
************************************/
@Override
public String toString() {
return ReflectionToStringBuilder.toStringExclude(this, "reserved", "id", "version", "createdBy", "createdDate", "lastModifiedBy", "lastModifiedDate", "deletedBy", "deletedDate", "_log");
}
@Override
public int hashCode() {
HashCodeBuilder hcb = new HashCodeBuilder(17, 37);
//@formatter:off
FieldUtils.getAllFieldsList(getClass()).stream()
.forEach(field -> {
if (!reserved.contains(field.getName()))
hcb.append(field);
});
//@formatter:on
return hcb.build();
}
@Override
public boolean equals(Object that) {
if (that == this)
return true;
if (!that.getClass().isInstance(this))
return false;
EqualsBuilder eb = new EqualsBuilder();
//@formatter:off
FieldUtils.getAllFieldsList(getClass()).stream()
.forEach(field -> {
field.setAccessible(true);
if (!reserved.contains(field.getName())) {
eb.append(ReflectionUtils.getField(field, this), ReflectionUtils.getField(field, that));
}
});
//@formatter:on
return eb.isEquals();
}
}
【问题讨论】:
标签: spring spring-boot jackson reactive hateoas