我有一个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()来更新用户,这有点不对吗?
答案 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测试的私有方法,我调用此方法来获取我的对象而不是直接调用模型