如何测试控制器在播放框架中正确写入数据库

时间:2012-01-17 12:50:59

标签: jpa playframework

我有一个FunctionalTest测试发布到控制器,然后在模型对象上断言,以确保控制器完成它的工作,如下所示:

@Test
public void editUser(){
    Logger.debug("Edit user test");
    createNewUser();
    final User user = User.<User>findAll().get(0);
    POST("/ManageUser/save", ImmutableMap.of(
            "user.id", user.getId().toString(),
            "user.username", "test",
            "user.email", "test@example.com",
            "user.fullName", "Test Different"
    ));
    User.em().flush(); 
    User.em().clear(); // this is required so that it works on the mem DB
    assertEquals(1, User.findAll().size());
    assertEquals("Test Different", User.<User>findAll().get(0).fullName);
    final User userAfterSave = User.<User>findAll().get(0);
    assertFalse("New user should not be admin.", userAfterSave.isAdmin);
}

当我使用mem数据库时,它会通过

%test.db.url=jdbc:h2:mem:play;MODE=MYSQL;LOCK_MODE=0

但是,如果我切换到mysql

%test.db=mysql://test:test@localhost/test

第二个断言失败,“失败,预期:<Test [Differen]t>但是:<Test [Tes]t>”。因此,当使用mysql时,控制器不能正确地保持用户。

我在这里缺少什么,是否有一些交易控制选项需要更改才能实现?

控制器只是调用user.merge()。save()来更新用户,这有点不对吗?

2 个答案:

答案 0 :(得分:2)

这是因为mem DB没有正确的事务性,这意味着测试线程每次读取都会获得新数据。但是对于mysql,测试线​​程在createNewUser()中读取用户,这意味着它的事务具有以前的版本。这并不明显,但POST()使用单独的事务启动一个新线程。要解决这个换出

User.em().flush(); 
User.em().clear();

JPAPlugin.closeTx(false);
JPAPlugin.startTx(false);

后者开始新的交易。

答案 1 :(得分:1)

在单独的作业中进行搜索,以确保正确查看修改(事务隔离)。这是一个例子

private FeedbackType findFeedbackType(final String name) throws ExecutionException, InterruptedException {
    return new Job<FeedbackType>() {
        @Override
        public FeedbackType doJobWithResult() throws Exception {
            return FeedbackType.findByName(name);
        }
    }.now().get();
}

这是我的Functional测试的私有方法,我调用此方法来获取我的对象而不是直接调用模型