2011-09-29 41 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()之前,我从数据库中获取模型解决了这个问题。