testing HQL query on hbm2dll with Junit - java

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:
create test object to put into DB
retrieve object from DB
compare objects
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?

Unit vs integration
First of all there is one thing you need to ask:
Do you want an Unit test or an Integration test
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:
Use rollback so that data is not stored between tests (guarantees test independence)
As your test suite grows, create an abstract class that holds the configuration and, e.g, exposes the EntityManager/sessionFactory. All your integration tests just need to extend this class, have the repository injected (in your example, inject DomainObjectRepositoryImpl into the test) and run the method you need to test.
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);
}
}

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
}

Related

how to do junit test for data base insertion using hibernate

I was trying to do j-unit test for project which insert values into database using hibernate classes. The program is creating tables and inserting values into database. but i am not able to do the j-unit part for the test?
I have attached the java table, but the value that i inserting using the test file is not display when i debugged it?
Sample.java
#Entity
public class Sample {
#Id
private int sid;
private String name;
public void set_sid(int sid)
{
this.sid=sid;
}
public void set_name(String name)
{
this.name=name;
}
public int get_sid()
{
return sid;
}
public String get_name()
{
return name;
}
}
SampleInsert.java
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class SampleInsert {
private Sample s;
private static SessionFactory sf;
public void insert() {
sf = new Configuration().configure(new File("C:/Users/ns068002/eclipse-workspace/JAXRS-HelloWorld1/src/main/java/com/javacodegeeks/enterprise/rest/jersey/hibernate.cfg.xml")).buildSessionFactory();
Session session = sf.getCurrentSession();
session.beginTransaction();
Sample s=(Sample) session.get(Sample.class, 1);
System.out.println(s+"2");
System.out.println(s.get_name());
session.getTransaction().commit();
}
}
SampleInsertTest.java
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class SampleTest {
Session session;
SampleInsert st;
#Before
public void setUp() {
session=mock(Session.class);
st=new SampleInsert();
}
#Test
public void test() {
Sample s=new Sample();
s.set_sid(1);
s.set_name("gopal");
Mockito.when(session.get(Sample.class,1)).thenReturn(s);
System.out.println(s+"1");
st.insert();
}
}
Looking at your code, I can not see how you would be able to mock/stub the Session or SessionFactory as neither of these things are "injected" into the class SampleInsert.
By "injected" I mean that the values are not passed into the class in some way, this is usually done using annotation with a framework like Spring, or via constructors.
It should be remembered that we are not testing the thing we are mocking, we are replacing the thing being mocked with a representation that is much simpler in order to test a component that makes use of the thing being mocked.
As an example of how you might use Mockito:
public interface SomethingToMock {
int returnSomeValueFor(int value);
}
public class ToBeTested {
private SomethingToMock session;
public ToBeTested(SomethingToMock session) {
this.session = session;
}
public void methodToTestA(int value) {
returnSomeValueFor(value);
}
public int methodToTestB(int value) {
int i = returnSomeValueFor(value);
return i * i;
}
}
#RunWith(MockitoJUnitRunner.class)
public class SomeTests {
#Mock
private SomethingToMock aMock;
private ToBeTested underTest;
#Before
public void setUp() {
underTest = new ToBeTested(aMock);
}
#Test
public void testOne() {
underTest.MethodToTestA(3);
verify(aMock).returnSomeValueFor(3);
}
#Test
public void testTwo() {
when(aMock.returnSomeValueFor(3)).thenReturn(2);
int r = underTest.methodToTestB(3);
assertEqual(r, 4);
}
}
In the example above we create an interface, this represents the thing to be mocked, we should aim to only mock interfaces and only those we or our team has created.
We then have a class that we need to test that uses the interface ToBeTested we can assume that concrete implementation of the interface are tested elsewhere in the project.
ToBeTested has two methods to test, one that has no return so has no side effects that we can see. The second method does some processing and has a side effect.
We then create a test class to test both methods, we insure it is setup to use Mockito (#RunWith(MockitoJUnitRunner.class) we then setup a mock using #Mock, the final setup step is to ensure our class has the mock "injected" into it, this is done in the setUp() method.
Finally we create two tests the first verifies that the mocked method is called, we don't have to set up a when for this in this case as no value will be returned from the method we are testing, just from the method being mocked I believe Mockito will return the default for an int.
The second test tests that a value is returned, thus we setup a when, when the mocked method is called in the way specified in the when the given value is returned and we can assert that the correct value is returned from the method under test, in this case using assertThat
This is the general layout of testing with Mockito. Effective testing is a huge topic, I would suggest you do some research on the web. The Mockito and JUnit docs are very good, and of course GitHub has many projects using both; one idea might be to look at the Mockito and Unit on Github and look at their testing.
Also the Mockito documentation does a very good job of explaining how, why and when to use mocking: http://static.javadoc.io/org.mockito/mockito-core/2.25.1/org/mockito/Mockito.html
I hope this helps.

Using #PostConstruct in a test class causes it to be called more than once

I am writing integration tests to test my endpoints and need to setup a User in the database right after construct so the Spring Security Test annotation #WithUserDetails has a user to collect from the database.
My class setup is like this:
#RunWith(value = SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureMockMvc
#WithUserDetails(value = "email#address.com")
public abstract class IntegrationTests {
#Autowired
private MockMvc mockMvc;
#Autowired
private Service aService;
#PostConstruct
private void postConstruct() throws UserCreationException {
// Setup and save user data to the db using autowired service "aService"
RestAssuredMockMvc.mockMvc(mockMvc);
}
#Test
public void testA() {
// Some test
}
#Test
public void testB() {
// Some test
}
#Test
public void testC() {
// Some test
}
}
However the #PostConstruct method is called for every annotated #Test, even though we are not instantiating the main class again.
Because we use Spring Security Test (#WithUserDetails) we need the user persisted to the database BEFORE we can use the JUnit annotation #Before. We cannot use #BeforeClass either because we rely on the #Autowired service: aService.
A solution I found would be to use a variable to determine if we have already setup the data (see below) but this feels dirty and that there would be a better way.
#PostConstruct
private void postConstruct() throws UserCreationException {
if (!setupData) {
// Setup and save user data to the db using autowired service "aService"
RestAssuredMockMvc.mockMvc(mockMvc);
setupData = true;
}
}
TLDR : Keep your way for the moment. If later the boolean flag is repeated in multiple test classes create your own TestExecutionListener.
In JUnit, the test class constructor is invoked at each test method executed.
So it makes sense that #PostConstruct be invoked for each test method.
According to JUnit and Spring functioning, your workaround is not bad. Specifically because you do it in the base test class.
As less dirty way, you could annotate your test class with #TestExecutionListeners and provide a custom TestExecutionListener but it seem overkill here as you use it once.
In a context where you don't have/want the base class and you want to add your boolean flag in multiple classes, using a custom TestExecutionListener can make sense.
Here is an example.
Custom TestExecutionListener :
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;
public class MyMockUserTestExecutionListener extends AbstractTestExecutionListener{
#Override
public void beforeTestClass(TestContext testContext) throws Exception {
MyService myService = testContext.getApplicationContext().getBean(MyService.class);
// ... do my init
}
}
Test class updated :
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#AutoConfigureMockMvc
#WithUserDetails(value = "email#address.com")
#TestExecutionListeners(mergeMode = MergeMode.MERGE_WITH_DEFAULTS,
value=MyMockUserTestExecutionListener.class)
public abstract class IntegrationTests {
...
}
Note that MergeMode.MERGE_WITH_DEFAULTS matters if you want to merge TestExecutionListeners coming from the Spring Boot test class with TestExecutionListeners defined in the #TestExecutionListeners of the current class.
The default value is MergeMode.REPLACE_DEFAULTS.

Mockito : Basic Code doubts

I am learning Mockito , i have trouble understanding few things. Suppose i want to test a Doa method which gets List of objects and saves it in DB by iterating ove the list . How do test it using Mockito. Below is the code example.
import java.util.Iterator;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
#Repository
public class AuditDaoImpl {
#PersistenceContext(unitName = "somepersistance")
EntityManager entityManager;
public <T> boolean saveAuditData(List<T> dataList) {
Iterator<Data> itr = (Iterator<Data>) dataList.iterator();
while (itr.hasNext()) {
Data Data = (Data) itr.next();
Audit audit = new Audit();
audit.setUserName(Data.getUserName());
entityManager.persist(audit);
}
return true;
}
}
Assuming that your test class is annotated and running with spring (by using #RunWith(SpringJUnit4ClassRunner.class) and #ContextConfiguration("classpath:applicationContext.xml")) annotation and you have this working. And if your main concern is to verify that entityManager.persist(audit); is invoked for each element, something like this should work
#Autowired //Autowired to get mockito to inject into the spring-handled dao
#InjectMocks
AuditDaoImpl auditDao;
#Mock
EntityManager entityManager;
#Test
public void saveAllAudit_entityManagerShouldPersistAll() {
List<Data> dataList = new ArrayList<>();
dataList.add(new Data("username"));
//add more to list
auditDao.saveAuditData(dataList);
verify(entityManager, times(1)).persist(anyObject());
}
If you actually need to test that it is persisted correctly, an in-memory database would be the way to go.
Mockito is poor for testing cases that deal with the persistence layer. You should use an embedded container to test the persistance layer. An embedded container is an in memory database that simulates your Database and is fast to create, making it ideal for unit tests.
Look at this SO question and read the SECOND answer :
Testing an EJB with JUnit

How to rollback transaction after class (using TestNg and Spring)?

Let's say we have the next test:
#ContextConfiguration(classes = {MyDaoContext.class})
public class MyDaoTest extends AbstractTransactionalTestNGSpringContextTests {
#Autowired
private MyDao dao;
#Test
public void insertDataTest() {
// insert data here and test something
}
#Test(dependsOnMethods = "insertDataTest")
public void modifyPreviouslyInsertedDataTest() {
// get previously inserted data and test something
}
}
Second test will fall because when we have finished first test the inserted data are gone.
Is there a way to rollback a transaction after all tests have finished their work?
Each test runs in its own transaction and rollbacks at the end. You can tune that by adding #Rollback(false) to your first test.
The problem now is that the transaction of insertDataTest has completed so you should remove what it has created manually. To do that, the class you extends from has several utility methods such as deleteFromTables or deleteFromTableWhere.
This should go ideally in an #AfterClass or something.
But that's not what I would do. I would factor out the data that are inserted by insertDataTest in a shared utility. That way, you could call it again in your second test and remove the dependsOnMethods. Having such dependency is not recommended as you can't run that test in isolation.
Try the following (which would work in JUnit, I'm not sure about TestBG)
#ContextConfiguration(classes = {MyDaoContext.class})
public class MyDaoTest extends AbstractTransactionalTestNGSpringContextTests {
#Autowired
private MyDao dao;
#Test
#Rollback(false)
public void insertDataTest() {
// insert data here and test something
}
#Test(dependsOnMethods = "insertDataTest")
public void modifyPreviouslyInsertedDataTest() {
// get previously inserted data and test something
}
}
In that case of course you would have to delete the data from the first method manually

Mocking CGLIB enhanced objects

Is it true that mockito can't mock objects that were already enhanced by CGLIB?
public class Article {
#Autowired
private dbRequestHandler
#Autowired
private filesystemRequestHandler
#Transactional
public ArticleDTO getArticleContents() {
//extractText() and then save the data in DTO
//extractImages() and then save the data in DTO
// some other calls to other databases to save data in dto
return articleDTO;
}
public void extractText() {
//call to DB
}
public void extractImages() {
// call to file system
}
}
public class IntegrationTest {
#Autowired
private Article article;
//setup method {
articleMock = Mockito.spy(article);
doNothing().when(articleMock).extractImages();
}
}
In the above example when it comes to doNothing().when(articleMock).extractImages(); it actually calls the real function. On a closer look articleMock gets enhanced two times. One cause of autowiring and second time cause of spying.
If I can't spy on enhaced objects, then how can I test the getArticle() method in my Integration test, so that I can verify a proper DTO is returned.
Note : I actually don't want to test the method which does filesystem calls. just the DB ones. thats why I need to test the getArticle method.
If I understand correctly your class is wired by Spring. Spring uses CGLIB to ensure transactional behaviour only if there is no interface, which is implemented by your object. If there is an interface, it uses simple JDK Dynamic Proxies. (see http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch08s06.html)
Maybe you could try to extract an interface, and let Spring to use dynamic proxies. Maybe then Mockito could perform better.
If you run as a true unit test and not as an integration test, you need not run in a container having Spring autowire for you. In one of your comments, I think you alluded to trying this, and you noted that there was an endless set of chained object references which you would have to provide as well. But there is a way around that. Mockito provides some predefined Answer classes that you can initialize your mock with. You may want to look at RETURNS_DEEP_STUBS, which will possibly get you around this problem.
Will you please update your question with ready-to-go compilable code. Here's some code review suggestions:
Issues with this question code:
Article.java missing import: org.springframework.beans.factory.annotation.Autowired
Article.java missing import: org.springframework.transaction.annotation.Transactional
Article.java attribute syntax issue: dbRequestHandler
Article.java attribute syntax issue: filesystemRequestHandler
Article.java method has no initialized return statement: articleDTO
Here's what you maybe should use as you questionCode with the above issues fixed:
Article.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
public class Article {
#Autowired
private Object dbRequestHandler;
#Autowired
private Object filesystemRequestHandler;
#Transactional
public ArticleDTO getArticleContents() {
// extractText() and then save the data in DTO
// extractImages() and then save the data in DTO
// some other calls to other databases to save data in dto
ArticleDTO articleDTO = null;
return articleDTO;
}
public void extractText() {
// call to DB
}
public void extractImages() {
// call to file system
}
}
IntegrationTest.java is a poor name for a testClass because it's to generic. I would suggest ArticleTest for a java unit test.
ArticleTest.java
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.beans.factory.annotation.Autowired;
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassWithPrivate.class)
public class ArticleTest {
#InjectMocks
private Article cut;
#Mock
private Object dbRequestHandler;
#Mock
private Object filesystemRequestHandler;
#Test
public void testeExtractImages() {
/* Initialization */
Article articleMock = Mockito.spy(cut);
/* Mock Setup */
Mockito.doNothing().when(articleMock).extractImages();
/* Test Method */
ArticleDTO result = cut.getArticleContents();
/* Asserts */
Assert.assertNull(result);
}
}
You can utilize AdditionalAnswers.delegatesTo method. In following example, the secondProxyDoingMocking declaration creates something like a spy (compare with implementation of spy() method) except it uses "lightweight" method delegation.
import org.mockito.AdditionalAnswers;
public class ArticleTest {
#Autowired
private Article firstProxyDoingAutowiring;
#Test
public void testExtractImages() {
Article secondProxyDoingMocking = Mockito.mock(Article.class,
Mockito.withSettings().defaultAnswer(
AdditionalAnswers.delegatesTo(firstProxyDoingAutowiring)
)
);
Mockito.doNothing().when(secondProxyDoingMocking).extractImages();
...
}
}
I didn't test this example, however I assembled it from my working code. My use case was similar: return constant value for given method, call real method for all remaining methods of Spring #Transactional-annotated bean.

Categories