我想检查我的持久性逻辑,所以我正在运行一些测试用例。
存储库类:
@Repository
public class MyRepository {
public void add(Object obj) {
/* Do some stuff here */
getSession().persist(obj);
}
}
测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { Context.class})
public class MyTests {
@Inject
private MyRepository myRepository;
@Test
@Rollback(true)
public void foo() {
/* Test logic */
myRepository.add(obj);
Assert.assert...;
}
}
单元测试:MyTests.java
包含测试一些与持久性有关的测试用例,但不测试实际的Hibernate持久性本身,这就是为什么getSession.persist()
语句已经过时了。
出于性能原因,我想阻止Hibernate将数据存储到我的数据库,即使整个数据交互被回滚。我的方法是模仿:getSession().persist()
。是否有更好的,或更具体的,更容易实现我的意图?
答案 0 :(得分:0)
创建一个接口,使用Hibernate persist()
方法实现它,并以这样的方式使用它:
public interface MyRepository {
public void add(Object obj);
}
public class MyRepositoryImpl implements MyRepository {
public void add(Object obj) {
getSession().persist(obj);
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { Context.class})
public class MyTests {
@Mock // we inject the mock instead of the true implementation
private MyRepository myRepository;
@Test
@Rollback(true)
public void foo() {
/* Test logic */
myRepository.add(obj); // the test uses the mocked version
Assert.assert...;
}
}
有许多Java库可以让你模拟对象,例如
答案 1 :(得分:0)
您需要能够模拟您的存储库对象,以便您可以在测试中使用模拟,并在应用程序的其余部分中使用真实模型。
DAO:
@Repository(value="MockRepo")
public class MockMyRepositoryImpl implments MyRepository {
@Override
public void add(Foo foo) {
//Do nothing here
}
}
测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { Context.class})
public class MyTests {
@Autowired
@Qualifier("MockRepo");
private MyRepository repo;
@Test
public void testFooSave() {
repo.add(obj);
}
}
另一种方法是使用另一个答案中详述的模拟框架。模拟框架更灵活,但如果你想要一些简单的东西,只需要工作,那么试试上面的内容。
答案 2 :(得分:0)
首先,Hibernate中有不同的id生成器。如果 identity 生成器(并非所有数据库都支持它),那么要为实体分配id,当调用session.persist
方法时,将调用 insert 查询。但是,例如,如果使用 sequence 或 uuid 生成器,那么<em> insert 将不会被触发(至少立即被触发)。
之后如果调用方法session.get
或session.load
加载持久化(在当前会话中)对象,则选择查询将不会被调用,因为它从Hibernate缓存中获取对象。但是如果使用HQL来选择数据,则会调用 select 查询。此外,在它之前(默认情况下)也会调用 insert 查询持久化对象。
可以使用 FlushMode 更改此设置。默认设置为 AUTO 。这意味着:
在查询执行之前,有时会刷新会话 确保查询永远不会返回陈旧状态。
但如果设置了getSession().setHibernateFlushMode(FlushMode.MANUAL)
:
只有在明确显示Session.flush()时才会刷新会话 应用程序调用。
这意味着在明确调用session.flush
之前,不会调用 insert 查询。如果进一步使用方法session.get
和session.load
,您的代码仍然有效(在当前会话中)。但是在选择 HQL查询的情况下 - 它不会找到该实体,因为它没有被持久化。所以要小心。