Reputation: 265
I want to check my persistence logic and so I am running some test cases.
Repository class:
@Repository
public class MyRepository {
public void add(Object obj) {
/* Do some stuff here */
getSession().persist(obj);
}
}
Test class:
@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...;
}
}
The unit test: MyTests.java
contains test cases which test some stuff that is related to persistence, but not the actual Hibernate persistence itself, so that's why the getSession.persist()
statement is obsolete.
For performance reasons, I want to prevent Hibernate from storing data to my database, even if the whole data interaction is rolled back. My approach would be to mock: getSession().persist()
. Is there a better, or more specifically, an easier way to achieve my intentions?
Upvotes: 2
Views: 1351
Reputation: 41
First of all, there are different id generators in Hibernate. If identity generator (not all the databases supports it), then to assign id to the entity, when session.persist
method is called, insert query will be called. But if, for example, sequence or uuid generator is used, then insert won't be triggered (at least right away).
After that if methods session.get
or session.load
are called to load persisted (in the current session) object, then select query won't be called, because it gets object from Hibernate cache. But if HQL is used to select data, then select query is called. Moreover before it (by default) insert query for persisted object is called too.
This can be changed with FlushMode. By default is set to AUTO. It means:
The Session is sometimes flushed before query execution in order to ensure that queries never return stale state.
But if getSession().setHibernateFlushMode(FlushMode.MANUAL)
is set:
The Session is only ever flushed when Session.flush() is explicitly called by the application.
Which means insert query won't be called until session.flush
is called explicitly. If methods session.get
and session.load
are further used your code will still work (in the current session). But in case of select HQL query - it won't find the entity since it wasn't persisted. So beware.
Upvotes: 2
Reputation: 6540
You need to be able to mock your repository object so that you can use the mock in tests, and use the real one in the rest of your application.
DAO:
@Repository(value="MockRepo")
public class MockMyRepositoryImpl implments MyRepository {
@Override
public void add(Foo foo) {
//Do nothing here
}
}
Test:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { Context.class})
public class MyTests {
@Autowired
@Qualifier("MockRepo");
private MyRepository repo;
@Test
public void testFooSave() {
repo.add(obj);
}
}
The alternative is to use a mocking framework as detailed in another answer. Mocking frameworks are more flexible, but if you want something simple that's just going to work then try the above.
Upvotes: 0
Reputation: 1188
Create an interface, implement it using the Hibernate persist()
method, and use it in such a way, that:
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...;
}
}
There are many Java libraries that let you mock objects, e.g.
Upvotes: 0