2015-09-29 57 views
0

在春天的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}); 

該對象由於必須是錯誤而無法驗證。

我發現如果我調試控制器是:

  1. 目的是在FormWrapper,和屬性的存在。
  2. 但是在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; 
    } 

回答

0

好吧,這是一個艱難的,所以我沒有真正期待任何人回答。但這是答案。我是對的,模擬在驗證中被調用。所以我不得不向格式化程序添加一個模擬方法(打印):

// check the formatter is working 
Mockito.when(mockInventoryFormatter.parse(((String)Mockito.anyObject()), ((Locale)Mockito.anyObject()))).thenReturn(oldInventory); 
// this was added 
Mockito.when(mockInventoryFormatter.print(Mockito.any(VariantInventory.class), Mockito.any(Locale.class))).thenReturn("20");