在为基于play1.2.4的webapp编写FunctionalTest时,我对如何正确编码感到困惑。混淆是关于涉及的事务边界。我读到每个测试都有自己的事务。
在我的应用程序中,用户可以登录并向购物车添加一些商品。然后他可以发送地址,以便将商品发送给他。
我创建了如下的私人帮助方法
private Cart buyItemsAsCustomer(String email,String pass) {
User user = User.find("byEmail", email).first();
//login
Response loginResponse = loginAsUser(email,pass);
Cart cart = new Cart(user);
cart.save();
addItemsToCart(cart.id);
return cart;
}
private Response loginAsUser(String email,String password) {
Map<String,String> loginUserParams = new HashMap<String,String>();
loginUserParams.put("username", email);
loginUserParams.put("password", password);
Response response = POST("/login",loginUserParams);
return response;
}
private Response addItemsToCart(Long cartId) {
Cart cart = Cart.findById(cartId);
Item item = Item.find("byIsbn","978-0451160522").first();
Map<String,String> addtocartParams = new HashMap<String,String>();
addtocartParams.put("cartId", cart.id.toString());
addtocartParams.put("quantity", "2");
String addtocarturl = "/items/addtocart/"+item.id.toString();
Response response = POST(addtocarturl,addtocartParams);
cart.refresh();//without this the assertion about number of items in cart fails!
return response;
}
private Map<String,String> createAddressParams(){
Map<String,String> addressParams = new HashMap<String,String>();
addressParams.put("addressline1", "1123,xx street");
addressParams.put("state", "new york");
addressParams.put("country", "US");
return addressParams;
}
最后我编写了FunctionalTest,它调用每个辅助方法来完成任务,然后执行断言
@Test
public void testCustomerCanAddAddress() {
Fixtures.loadModels("data.yml");
assertTrue(Address.findAll().size()==0);
Cart joncart = buyItemsAsCustomer("jon@gmail.com","jon");
assertFalse(jonart.cartItems.size()==0);
Map<String,String> addressParams = createAddressParams();
POST("/items/address/"+joncart.customer.getId().toString(),addressParams);
assertTrue(Address.findAll().size()==1);
}
运行它会产生
A java.lang.RuntimeException has been caught, java.util.concurrent.ExecutionException: play.exceptions.JavaExecutionException
POST("/items/address/"+joncart.customer.getId().toString(),addressParams);
我认为这是因为某些交易边界问题,但我不确定。有人请帮我纠正这个问题吗?我真的希望得到一些关于如何在这种情况下编写测试的帮助。
我已粘贴了堆栈跟踪here
答案 0 :(得分:3)
您的测试很奇怪,因为您混合了http调用和模型调用。功能测试纯粹是http调用。您测试控制器层
如果您需要一些模拟数据,您必须在另一个事务中创建它们,最简单的方法是在特定方法中使用作业。如果您想检索数据以确保测试通过,也是一样。
@Before
public void cleanUp() throws Exception {
new Job() {
@Override
public void doJob() throws Exception {
Fixtures.deleteDatabase();
Fixtures.loadModels("data.yml");
}
}.now().get();
}
答案 1 :(得分:2)
java.util.concurrent.ExecutionException不一定是由事务引起的。我的功能测试得到了这个异常,因为我没有为 routes 文件中的控制器方法指定正确的POST路由。
但是,如果我需要使用修改数据库的POST请求,我需要检查功能测试方法中的结果,我使用
Response response = POST("address/to/my/controller/", params);
JPAPlugin.closeTx(false);
JPAPlugin.startTx(false);
// Check here that the changes to the database are correct!