我试图SpringJunit4ClassRunner通过使用@Transactional注释来测试我的DAO类,而不会在完成后留下数据.我的DAO类包含(剥离):
@Repository
public class IdsFunctionJpaController {
@PersistenceContext
EntityManager em;
public void save(IdsFunction function) {
if (function.getId() == 0) {
create(function);
} else {
update(function);
}
}
@Transactional
private void create(IdsFunction idsFunction) {
try {
em.persist(idsFunction);
}
catch (Exception e) {
System.out.println(e);
} finally {
em.close();
}
}
@Transactional
private void update(IdsFunction function) {
try {
em.merge(function);
} finally {
em.close();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的首发JUnit测试用例是
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/applicationContext.xml"} )
public class IdsFunctionJpaControllerTest {
@Autowired
IdsFunctionJpaController dao;
@Test
@Transactional
public void addFunction() {
IdsFunction function = new IdsFunction();
function.setDescription("Test Function Description");
dao.save(function);
assertTrue(function.getId() != 0);
}
}
Run Code Online (Sandbox Code Playgroud)
我在这里尝试做的只是测试实体已经创建,但是这个测试失败了.如果我删除@Transactional注释,则测试通过,但测试实体仍保留在数据库中.我究竟做错了什么?
问候
你正在敲打JDK代理.
您的dao.save()方法是非事务性的,它尝试调用事务方法create()和update().但事务性事件发生在类外的JDK代理中,而save方法已经在类中.
请参阅我之前的答案以供参考.
解决方案:
save()方法具有事务性参考:
更新:我被@TransactionalDao方法中存在令人困惑的注释所误导.你应该删除它们,它们什么也不做,让人迷惑.
正如您在上面发布的链接中所看到的那样,@Transactional注释只有在公共方法中出现时才会生效.这些方法将从Spring bean外部调用(因此,您不能在一个代理一个或多个代理的类中使用一个方法同类的方法).
Spring提供了特殊的事务测试支持类,如9.3.5.4事务管理中所述.如果您让测试类扩展,则AbstractTransactionalJUnit4SpringContextTests在每次测试后都会获得自动事务回滚.在大多数情况下,这正是您所需要的.
您需要刷新会话.通常这发生在交易结束时,这就是为什么你通常只需要在测试中担心它.
注入EntityManager到测试类中并em.flush()在保存后调用.
此外,您的DAO层不应该是事务性的.事务通常仅在服务层中有意义.
事实上,你的DAO也是完全错误的,这个测试无法显示.这些事务注释将无效,因为它们是内部方法调用.你也应该永远不要关闭EntityManager自己 - 容器(Spring)会为你做这件事.另外,不要捕获泛型Exceptions,当你做的时候不要只记录并忽略它们.异常应该传播到应该正确处理它们的服务层.另外,不要打印到stdout,使用适当的日志框架.
| 归档时间: |
|
| 查看次数: |
12833 次 |
| 最近记录: |