Reputation: 2120
How can I test HQL query with JUnit tests?
I have mapped Entity Class:
@Entity
@Table(name = "DOE")
public DomainObjectEntity {
//some attributes
}
which represents domain objects:
public class DomainObject {
//some attributes
}
I also have repository interface for my domain objects:
public interface DomainObjectRepository {
/**
* Gets entity by some attribute
*
*/
DomainObject getDomainObjectByObjectId(String objectId);
}
this interface is implemented in
@Repository
public class DomainObjectRepositoryImpl implements DomainObjectRepository {
@Inject
private DomainObjectEntityJPARepository entityRepository;
@Override
public DomainObjectgetDomainObjectById(String parcelId) {
//this converts my entity to domain object
return entityRepository.findByDomainObjectId(DomainObjectId.getStr()).getDomainObject();
}
}
my JPA Entity repository looks like this:
public interface DomainObjectEntityJPARepository extends JpaRepository<DomainObjectEntity, String> {
/**
* get DomainObject with requested id
*
* @param objectId - objects id
* @return DomainObject
*/
@Query("some query to be tested")
DomainObjectEntity findByDomainObjectId(@Param("objectId") String objectId);
}
and finally i want to write a simple JUnit test to check if query to findByDomainObjectId
returns the correct object. I think my test should look like this:
i have setted up a hbm2dll with import.sql to create and populate my DB but how can i access it from Junit test by calling method findByDomainObjectId
?
Upvotes: 2
Views: 1622
Reputation: 2120
Since I wanted to test only query, proper solution was to @autowire
JPArepository and then in setup, populate it with data, this way tests were bound only with DB structure and not the data inside
public class EntityObjectJPARepositoryTest {
@Autowired
DomainObjectEntityJPARepository domainObjectRepo;
DomainObjectEntity entity;
@Before
public void Setup(){
entity = new DomainObjectEntity ()
//setup entity
domainObjectRepo.save(entity);
}
@Test
public void testfindByDomainObjectId(){
DomainObjectEntity res = domainObjectRepo.findByDomainObjectId(objectid);
Assert.assertEquals(entity.getId(), res.getId());
}
//everything else
}
Upvotes: 0
Reputation: 1057
Unit vs integration
First of all there is one thing you need to ask:
An unit test is fast (ie, milliseconds) to run and is, well, unitary - meaning it doesn't touch the database.
An integration test is heavier and, in case of a database test, will touch the db.
While it is usually preferable to create unit tests, in your case it seems you want an integration test - you actually want to test the call to the database and check if the query does what you think it does.
When to load data
I would suggest that in your integration test you don't preload data with import.sql (or at least think very carefully if this is what you want). The reason for this is that, as your test suite grows, you'll need the database in one state for test A, another state for test B, and so on, and you'll quickly end up in a situation where you'll have incompatible states.
You'll also end up with slower tests if you load too much data via SQL.
My advise would be: try to create/manipulate the data in your test.
How to test
How to test it depends on how you load your hibernate in production. Judging by the code you've shown, I believe you might be using a Dependency injection mechanism to start up hibernate's EntityManager (or SessionFactory), like Spring.
If this is the case, you can use spring to configure you integration test. The main suggestions here would be:
Below is a very simple abstract test I have (in my case I'm using a SessionFactory):
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={
"/spring-SF-tests.xml",
"/spring-transaction.xml"
})
@TransactionConfiguration(transactionManager="txManager", defaultRollback=true)
public abstract class HibernateAbstractTest extends AbstractTransactionalJUnit4SpringContextTests {
@Autowired
protected SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
public Session getSession(){
return sessionFactory.getCurrentSession();
}
public void save(Object object){
getSession().save(object);
}
public void update(Object object){
getSession().update(object);
}
}
Upvotes: 1