问题描述
我正在尝试在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","title":"Primera página"
},{
"rel":"prev","title":"Página previa"
},{
"rel":"next","title":"Siguiente página"
},{
"rel":"last","title":"Última página"
},{
"rel":"page-1","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()),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","_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.hateoas:
use-hal-as-default-json-media-type: false