2

在为基于 play1.2.4 的 webapp 编写功能测试时,我对如何正确编码有点困惑。困惑在于所涉及的事务边界。我在某处读到每个测试都有自己的事务。

在我的应用程序中,用户可以登录并将一些物品添加到购物车中。然后他可以提供一个地址,以便可以将物品发送给他。

我创建了如下的私有辅助方法

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;
}

最后,我编写了函数测试,它调用这些辅助方法中的每一个来执行任务,然后执行断言

@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);

我认为这是由于某些事务边界问题而发生的,但我不确定..有人可以帮我纠正这个吗?..我真的很想在这种情况下如何编写测试方面得到一些帮助..

我在这里粘贴了堆栈跟踪

4

2 回答 2

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();
}
于 2012-03-05T15:45:57.033 回答
2

java.util.concurrent.ExecutionException 不一定是由事务引起的。我的功能测试出现了这个异常,因为我没有在路由文件中为我的控制器方法指定正确的 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!
于 2012-03-05T15:00:13.590 回答