2011-09-29 39 views
2

我寫了一個功能測試來檢查添加項目到購物車。對於用戶能夠添加項目到購物車,他需要登錄。所以,我創建了一個方法登錄用戶和另一種方法來添加項目。在測試中的addtocart方法之前和之後,我正在檢查購物車內容的大小。當我以開發模式運行應用程序時,addtocart功能沒有任何問題(我可以檢查該數據庫也是 - 這是postgres,而不是在內存數據庫)。addtocart測試失敗。添加項目到購物車時,功能測試在playframework中失敗

這增加了項目到購物車

控制器方法
public static void addItemToCart(Long productId,Long cartId,String quantity) { 
    Product product = Product.findById(productId); 
    ShopCart cart = ShopCart.findById(cartId); 
    int qty = Integer.parseInt(quantity); 
    CartItem cartItem = new CartItem(product,qty); 
    cart.addItem(cartItem); 
    cart.save(); 
    System.out.println("Controller::addItemToCart()::cart id="+cart.id+" has="+cart.cartItems.size()+" items); 
} 

我的測試方法是

@Test 
public void testUserCanAddItemsToCart() { 
    Fixtures.loadModels("data.yml"); 
    User user = User.find("byEmail","[email protected]").first(); 
    loginAsCustomer("[email protected]","userpass"); 
    ShopCart usercart = new ShopCart(user); 
    usercart.save(); 
    System.out.println("BEFORE ADD::usercart="+usercart.id+" has :"+usercart.cartItems.size()+" items"); 
    assertTrue(usercart.cartItems.size()==0); 
    addItemsToCart(usercart); 
    System.out.println("AFTER ADD::usercart="+usercart.id+" has :"+usercart.cartItems.size()+" items"); 
    assertFalse(usercart.cartItems.size()==0);//why does this fail? 

} 

private Response addItemsToCart(ShopCart cart) { 
     Product pdt = Product.find("byIsbn","654-0451160522").first(); 
     assertNotNull(pdt); 
     System.out.println("addItemsToCart():BEFORE ADD cart="+cart.id+" has="+cart.cartItems.size()); 
     Map<String,String> addtocartParams = new HashMap<String,String>(); 
     addtocartParams.put("cartId", cart.id.toString()); 
     addtocartParams.put("quantity", "2"); 
     String addtocarturl = "/items/addtocart/"+pdt.id.toString(); 
     Response response = POST(addtocarturl,addtocartParams); 
     System.out.println("addItemsToCart():AFTER ADD cart="+cart.id+" has="+cart.cartItems.size()); 
     return response; 
    } 

控制檯輸出我得到的是

BEFORE ADD::usercart=48 has :0 items 
addItemsToCart():BEFORE ADD cart=48 has=0 
Controller::addItemToCart()::cart id=48 has=1 items 
addItemsToCart():AFTER ADD cart=48 has=0 
AFTER ADD::usercart=48 has :0 items 

這裏,在控制器的方法,購物車實例(id = 48)在保存到db後有1個項目。但在測試方法中,相同的購物車實例ID有0個內容。

我註釋掉了assertFalse方法,並使用cartId從db中檢索了購物車。然後,同一id的購物車有0個內容。我不明白爲什麼會發生這種情況。

//測試方法體..modified

ShopCart cart = ShopCart.findById(usercart.id); 
System.out.println("AFTER ADD::cart="+cart.id+" has :"+cart.cartItems.size()+" items");   
assertFalse(cart.cartItems.size()==0);//why does this fail? 
+0

好問題!這會從數據庫獲取數據的狀態,所以對其他情況可能非常有用。 – andronikus

回答

3

它失敗,因爲你的測試方法所使用的購物車實例,並通過addItemToCart方法所使用的購物車實例是不同的。每個事務都有自己的實體實例。當其他事務更新由此實體映射的行時,JPA不會自動刷新實體。

您應該在調用addItemsToCart以檢查數據庫中的購物車是否已添加內容後,從數據庫中重新加載購物車。

+0

感謝您的答覆..我想我試過在問題的最後部分,通過使用ShopCart.findById(..)..仍然返回一個具有相同ID但沒有內容的實例! – jimgardener

+1

是的,但由於您仍處於同一事務中,因此您將從第一級緩存中重新讀取購物車,而不是從數據庫中讀取購物車。嘗試刷新購物車,或從第一級緩存中逐出並重新加載。或者使用兩個不同的交易。 –

+0

謝謝..解決了它..你給了我很多咀嚼..再次感謝 – jimgardener

0

我是面向對象思維的奴隸,所以我想知道的是,你有沒有想過要使addItemsToCart()成爲ShopCart類的方法?我設想是這樣的:

... 
ShopCart usercart = new ShopCart(user); 
usercart.addItemsToCart(pdt); 
usercart.save(); 

String addtocarturl = "/items/addtocart/"+pdt.id.toString(); 
Response response = POST(addtocarturl,addtocartParams); 
return response; 

這是我認爲只是更容易使左右(或恢復)一個ShopCart對象,修改它,並把它在數據庫中。這就是我會如何避免這種情況。

0

我有同樣的問題,並在我的測試中添加JPA.em()。clear()之前,我從數據庫中獲取模型解決了這個問題。