我有一个 OrderInfo 类:
@ApiModel(description = "object needed to make an order")
public class OrderInfo implements Serializable {
private static final long serialVersionUID = 1L;
@JsonProperty("purchase")
private PurchaseInfo purchase = null;
@JsonProperty("paymentMode")
private PaymentMode paymentMode = null;
@JsonProperty("serialNumber")
private String serialNumber = null;
public OrderInfo purchase(PurchaseInfo purchase) {
this.purchase = purchase;
return this;
}
@ApiModelProperty(required = true, value = "coming from commercialization")
@NotNull
@Valid
public PurchaseInfo getPurchase() {
return purchase;
}
public void setPurchase(PurchaseInfo purchase) {
this.purchase = purchase;
}
public OrderInfo paymentMode(PaymentMode paymentMode) {
this.paymentMode = paymentMode;
return this;
}
@ApiModelProperty(required = true, value = "")
@NotNull
@Valid
public PaymentMode getPaymentMode() {
return paymentMode;
}
public void setPaymentMode(PaymentMode paymentMode) {
this.paymentMode = paymentMode;
}
public OrderInfo serialNumber(String serialNumber) {
this.serialNumber = serialNumber;
return this;
}
@ApiModelProperty(value = "The serial number of the registered device")
public String getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
}
具有 PurchaseInfo 子对象:
@ApiModel(description = "Info necessary to order a video, an episode or a season")
public class PurchaseInfo implements Serializable {
private static final long serialVersionUID = 1L;
@JsonProperty("id")
private String id = null;
@JsonProperty("pricingId")
private String pricingId = null;
@JsonProperty("price")
private Double price = null;
@JsonProperty("type")
private ArticleType type = null;
public PurchaseInfo id(String id) {
this.id = id;
return this;
}
@ApiModelProperty(required = true, value = "id of the commercialization")
@NotNull
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public PurchaseInfo pricingId(String pricingId) {
this.pricingId = pricingId;
return this;
}
@ApiModelProperty(required = true, value = "additional pricing of the commercialization")
@NotNull
public String getPricingId() {
return pricingId;
}
public void setPricingId(String pricingId) {
this.pricingId = pricingId;
}
public PurchaseInfo price(Double price) {
this.price = price;
return this;
}
@ApiModelProperty(required = true, value = "price of the commercialization")
@NotNull
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public PurchaseInfo type(ArticleType type) {
this.type = type;
return this;
}
@ApiModelProperty(required = true, value = "")
@NotNull
@Valid
public ArticleType getType() {
return type;
}
public void setType(ArticleType type) {
this.type = type;
}
}
以及生成的相应 FieldDescriptor 类:
public class OrderInfoFieldDescriptor {
public static FieldDescriptor[] fdOrderInfo = new FieldDescriptor[] {
fieldWithPath("purchase").description("coming from commercialization").type(PurchaseInfo.class),
fieldWithPath("paymentMode").description("").type(PaymentMode.class),
fieldWithPath("serialNumber").description("The serial number of the registered device").type(java.lang.String.class).optional() };
public static FieldDescriptor[] fdOrderInfoList = new FieldDescriptor[] {
fieldWithPath("[].purchase").description("coming from commercialization").type(PurchaseInfo.class),
fieldWithPath("[].paymentMode").description("").type(PaymentMode.class),
fieldWithPath("[].serialNumber").description("The serial number of the registered device").type(java.lang.String.class).optional() };
}
并且:
public class PurchaseInfoFieldDescriptor {
public static FieldDescriptor[] fdPurchaseInfo = new FieldDescriptor[] {
fieldWithPath("id").description("id of the commercialization").type(java.lang.String.class),
fieldWithPath("pricingId").description("additional pricing of the commercialization").type(java.lang.String.class),
fieldWithPath("price").description("price of the commercialization").type(java.lang.Double.class),
fieldWithPath("type").description("").type(ArticleType.class) };
public static FieldDescriptor[] fdPurchaseInfoList = new FieldDescriptor[] {
fieldWithPath("[].id").description("id of the commercialization").type(java.lang.String.class),
fieldWithPath("[].pricingId").description("additional pricing of the commercialization").type(java.lang.String.class),
fieldWithPath("[].price").description("price of the commercialization").type(java.lang.Double.class),
fieldWithPath("[].type").description("").type(ArticleType.class) };
}
为了生成带有OrderInfo.class类型的requestBody和responseBody的HTTP POST而调用嘲笑Mvc.perform时:
mockMvc.perform(postRequest)
.andDo(document("orderInfoCreate", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()),
pathParameters(parameterWithName("username").description("the name of the user")),
responseFields(OrderInfoFieldDescriptor.fdOrderInfo),
requestFields(OrderInfoFieldDescriptor.fdOrderInfo))).andExpect(status().isCreated())
.andExpect(content().json(orderInfoAsJson));
验证适用于 paymentMode 和 serialNumber ,但对于 purchase 无效,
org.springframework.restdocs.snippet.SnippetException: The following parts of the payload were not documented:
{
"purchase" : {
"id" : "purchaseId",
"pricingId" : "pricingId",
"price" : 12.0,
"type" : "EPISODE"
},
"serialNumber" : "serialNumber"
}
即使请求正文和响应正文看起来不错:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /api/users/myUserName/orders
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Host:"host:posrt", Accept:"application/json;charset=UTF-8", Cookie:"identity=cookieForTest"]
Body = {"purchase":{"id":"purchaseId","pricingId":"pricingId","price":12.0,"type":"EPISODE"},"paymentMode":"POSTPAID","serialNumber":"serialNumber"}
Session Attrs = {}
并且:
MockHttpServletResponse:
Status = 201
Error message = null
Headers = [Content-Type:"application/json;charset=UTF-8"]
Content type = application/json;charset=UTF-8
Body = {"purchase":{"id":"purchaseId","pricingId":"pricingId","price":12.0,"type":"EPISODE"},"paymentMode":"POSTPAID","serialNumber":"serialNumber"}
Forwarded URL = null
Redirected URL = null
Cookies = []
从Spring Boot 1x迁移到2x后出现了问题。
您是否知道可能是什么问题?
谢谢:)
答案 0 :(得分:1)
您似乎正在依靠purchase
来记录purchase
及其包含的所有内容,即purchase.id
,purchase.pricingId
,purchase.price
和{{ 1}}。此功能在REST Docs(含1.1版)及以下版本中都有效,但它产生了一个问题,即人们在记录嵌套字段时会意外地漏掉他们对父字段的记录。 this question和this Spring REST Docs issue中对此进行了讨论。该问题在REST Docs 1.2中进行了更改,默认情况下,记录字段不再记录其所有后代。您会受到此更改的影响,因为升级到Spring Boot 2意味着您也已经升级到REST Docs 2。
如果要保留现有行为,而仅使用purchase.type
来记录它及其所有后代,则应将purchase
替换为fieldWithPath
。如果要记录subsectionWithPath
下的所有内容,则应为purchase
,purchase.id
,purchase.pricingId
和purchase.price
添加额外的描述符。