правильный способ написания FunctionalTest в playframework - PullRequest
2 голосов
/ 01 марта 2012

При написании FunctionalTest для веб-приложения на основе play1.2.4 я был немного озадачен тем, как правильно его кодировать. Путаница связана с границей транзакции. Я где-то читал, что у каждого теста есть собственная транзакция.

В моем приложении пользователь может войти в систему и добавить некоторые элементы в корзину. Затем он может дать адрес, чтобы элементы могли быть отправлены ему.

Я создал частные вспомогательные методы, как показано ниже

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

Я думаю, что это происходит из-за какой-то проблемы с границей транзакции, но я не уверен ... Может кто-нибудь помочь мне исправить это? .. Мне действительно нужна помощь в том, как тест должензаписать в этом случае ..

Я вставил трассировку стека сюда

Ответы [ 2 ]

3 голосов
/ 05 марта 2012

Ваш тест странный, потому что вы смешиваете вызовы http и модели звонков. Функциональный тест - это чисто http звонки. Вы тестируете свой слой контроллеров

Если вам нужны фиктивные данные, которые вы должны создать в другой транзакции, для меня самый простой способ сделать это - использовать задание определенным способом. То же самое, если вы хотите получить данные, чтобы убедиться, что ваш тест пройден.

@Before
public void cleanUp() throws Exception {
    new Job() {
        @Override
        public void doJob() throws Exception {
            Fixtures.deleteDatabase();
            Fixtures.loadModels("data.yml");
        }

    }.now().get();
}
2 голосов
/ 05 марта 2012

Исключительная ситуация 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!
...