在春天的mvc應用程序中,我提交了id並使用格式化程序將該id轉換爲對象。它在容器中運行良好。BindingResult.getFieldValue()在測試上下文中爲格式化值返回null
但在單元測試環境中,我看到一個問題。
我嘲笑格式化程序總是返回我的測試值,這很好,它被注入ModelAttribute。但在BindingResult中,例如對result.getFieldValue("location")
的調用返回null,但僅在MockMvc上下文中。
這是測試用例:
/**
* Tests the inventory update for existing inventory records.
* @throws Exception
*/
@Test
public void testUpdateExistingProductInventory() throws Exception{
logger.entry();
VariantInventory oldInventory = new VariantInventory();
oldInventory.setId(20l);
Product product = ProductBuilder.buildBasicExisting();
Location location = new Location();
location.setId(3l);
ProductVariant variant = new ProductVariant();
variant.setId(2l);
// check the formatter is working
Mockito.when(mockProductFormatter.parse(((String)Mockito.anyObject()), ((Locale)Mockito.anyObject()))).thenReturn(product);
Product p = mockProductFormatter.parse("1", null);
Assert.assertEquals(p, product);
// check the formatter is working
Mockito.when(mockLocationFormatter.parse(((String)Mockito.anyObject()), ((Locale)Mockito.anyObject()))).thenReturn(location);
Location l = mockLocationFormatter.parse("3", null);
Assert.assertEquals(l, location);
// check the formatter is working
Mockito.when(mockVariantFormatter.parse(((String)Mockito.anyObject()), ((Locale)Mockito.anyObject()))).thenReturn(variant);
ProductVariant pv = mockVariantFormatter.parse("2", null);
Assert.assertEquals(pv, variant);
// check the formatter is working
Mockito.when(mockInventoryFormatter.parse(((String)Mockito.anyObject()), ((Locale)Mockito.anyObject()))).thenReturn(oldInventory);
VariantInventory v = mockInventoryFormatter.parse("20", null);
Assert.assertEquals(v, oldInventory);
this.mockMvc.perform(MockMvcRequestBuilders.post("/ajax/products/update/inventory")
.param("product", "1")
.param("variant", "2")
.param("location", "3")
.param("status", "ACTIVE")
.param("quantityOnHand", "30.5")
.param("lowStockQuantity", "10")
.param("inventory", "20")
)
.andExpect(status().isOk());
Mockito.verify(mockInventoryService, Mockito.times(1)).updateExisting(Mockito.eq(oldInventory), Mockito.any(VariantInventory.class));
logger.exit();
}
這是控制器的相對部分:
@RequestMapping(value = "/ajax/products/update/inventory", method= RequestMethod.POST)
public @ResponseBody
AJAXResponse updateProductInventory(@ModelAttribute ProductInventoryFormWrapper formWrapper, BindingResult result,
ModelMap map) {
logger.entry();
logger.debug("Getting product data");
if (!result.hasErrors()) {
inventoryValidator.validate(formWrapper, result);
}
}
然後跳過幾個項目,這是一個失敗的相關驗證,我在哪裏作爲字段傳遞location
。
ValidationUtils.rejectIfEmptyOrWhitespace(errors, field, "required.field", new String[]{label});
該對象由於必須是錯誤而無法驗證。
我發現如果我調試控制器是:
- 目的是在FormWrapper,和屬性的存在。
- 但是在BindingResult對象中,如果我調用'getFieldValue('location')`這是Spring驗證代碼中調用的內容,它返回null,因此驗證器會拒絕該值。
因此,由於某種原因,綁定結果沒有註冊格式化字段或東西。請注意,這隻發生在單元測試中,而不是容器中。
有誰知道如何解決?
快速編輯:
我做了一些更多的調試,並且它在這個代碼塊從AbstractPropertyBindingResult
失敗。 value
沒問題,直到調用conversionService來轉換它。我沒有下載超出該方法的源代碼,所以我無法確切知道它失敗的原因,但在convert
方法中,它正在從適當的值轉換爲空值。我認爲是因爲我使用了MockObjects,也許它調用了我沒有預料到會返回的值。
@Override
protected Object formatFieldValue(String field, Object value) {
String fixedField = fixedField(field);
// Try custom editor...
PropertyEditor customEditor = getCustomEditor(fixedField);
if (customEditor != null) {
customEditor.setValue(value);
String textValue = customEditor.getAsText();
// If the PropertyEditor returned null, there is no appropriate
// text representation for this value: only use it if non-null.
if (textValue != null) {
return textValue;
}
}
if (this.conversionService != null) {
// Try custom converter...
TypeDescriptor fieldDesc = getPropertyAccessor().getPropertyTypeDescriptor(fixedField);
TypeDescriptor strDesc = TypeDescriptor.valueOf(String.class);
if (fieldDesc != null && this.conversionService.canConvert(fieldDesc, strDesc)) {
return this.conversionService.convert(value, fieldDesc, strDesc);
}
}
return value;
}