在play框架中编写Functional Test的正确方法

时间:2012-03-01 04:48:52

标签: java transactions playframework playframework-1.x

在为基于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

2 个答案:

答案 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!