I am getting the lazy initialization exception while testing the spring service layer with TestNG testcases. Could you please help me out to resolve the issue. Not sure if I'm missing any thing in the below testcase. But if I create and execute the testcase for same method in Dao layer then its working fine.
You have the following mapping
<set name="validResponses" lazy="true" inverse="true"
which lazily loads the InspectionQuestion.validResponses field.
I'm going to assume that
InspectionQuestion iq = inspectionStepQuestionService.getActiveInspectionQuestionByCode(QuestionType.COUNTRY_ORIGIN);
is done within a Session and a Transaction. When the method returns, the Transaction is committed and the Session is closed. As such, any fields that are not eagerly loaded are in an un-initialized stated. Trying to initialize them after this will cause the LazyInitializationException that you are seeing.
The simple solution would be to change lazy="true" to lazy="false", but this may not be what you want always.
Instead, maybe change your InspectionStepQuestionService methods to fully initialize your entities when required
Hibernate.initialize(inspectionQuestion /* or entity to return */);
By adding the below annotation in the test class, I'm able to maintain the session. #TransactionConfiguration(transactionManager="hibernateTransactionManager", defaultRollback=true).
Related
I have application managed by Spring v4. I'd like to user AOP to add logging without code change but.. Generally I have tow component managed by Spring one is used for creating second one, let's call them A and B. During crating A method B.initialize is being called. To log the start of initializing I have Aspect component with appropriate pointut:
#Around("execution(* com.aop.B.initialize())")
So my problem: method initialize has a few nullable properties which will be initialized in the future with another framework so when I call proceed() the result is NullPointerException, but... when I comment proceed method and pointcut method are invoked everything works fine. Result is two records in log (those which should be before and after proceed method) and well initialized component A.
Could somebody explain me what happened here? I mean, does Around advice without direct proceed invoking works in the same way ans the Before one?
I am very new for testng(unit testing) and mockito. I have read some articles and went through some code snippets on Internet. But still I have some doubts regarding unit testing with testng & mockito in spring framework.
For unit testing a service layer we mock a DAO. What if I want to test a function wich fetch some data from database and do some operations. How does mock DAO works here. From where mocked DAO will get some data for testing such a function.
If am doing a validation like Data not present in database and I want to test wheather it throws correct exception for that. So it needs some values in database and mocked DAO will check if data present in that predefined database(in-memory). How to provide such a data.
Does dataprovider helps to provide a data to used by DAO. If yes, How it can be done?
Please correct me if my understanding regarding unit testing is correct. Please let me know where I am getting it wrong if I miss understood a concept.
Thank you.
1) Besides UnitTests, you also need Integration and / or Acceptance-Tests.
The Unit-Tests will test that your SUT - Single Unit of Test, in this case a specific service class works as intended, without integrating it with other classes or systems (DB). However, additionally I would write an Integration Test for this Service that retrieves / manipulates test data from the database. This test should ideally not make any assumptions about the data in the database, so inserting the data you will be looking for, before executing the test, is recommended, e.g. using a #Before annotation and actually committing this test data into the test database. However, I further recommend you to do a proper cleanup of the database, in the #After test method. Auto rolling back the data could be done, but is not as optimal, especially if you have a persistence framework like Hibernate or JPA in between. Only when you work on committed data that is really in the physical (not virtual!) dabase, you can be 100% sure your test succeeded.
If I correctly understood your intend, this actually sounds like a perfect reason for mocking your DB / persistence object - make it throw the expected exception / return an empty result, that test that your code behaves as expected on this condition.
A TestNG Dataprovider actually does the opposite of what you are looking for - it is a way to provide an array of data to your test method:
org.testng.annotations.DataProvider
Annotation Type DataProvider
Mark a method as supplying data for a test method. The data provider name defaults to method name. The annotated method must return an Object[][] where each Object[] can be assigned the parameter list of the test method. The #Test method that wants to receive data from this DataProvider needs to use a dataProvider name equals to the name of this annotation.
I'm struggling with a problem I and can not find out proper solution or even a cause neither in hibernate docs, sources nor S/O.
I have spring/hibernate application with DAO-Service-RPC layers, where DAO provides Hibernate entities and Service DTOs for RPC. Therefore I'm converting (mapping by Dozer) Entities to DTOs in service methods and mapping DTOs back to Entities there as well.
Mapping is as follows (not full method, checking ommited):
#Transactional
public updateAuthor(Author author) {
AuthorEntity existingEntity = this.authorDao.findById(author.getId());
this.authorDao.detach(existingEntity);
this.authorAssembler.toEntity(author, existingEntity, null);
this.authorDao.merge(existingEntity);
}
I have unit test classes annotated by #Transactional to avoid test data bleeding. Now, I realized, that there is something, I don't understand, going on in Service.
When I have my test class annotated by #Transactional, calling detach() seems to work (i.e. Hibernate is not reporting org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session, but #Version number on entity is not incremented properly (as if the parent (unit test)) TX was still holding on.
When I remove my test class annotation, mapping throws org.hibernate.LazyInitializationException: failed to lazily initialize a collection - which makes sense on it's own, because the entity is detached from session. What I don't understand is, why this exception is NOT thrown when the test class is annotated. As I understand, entity is detached from the current session in both cases.
My other question is - assuming the entity is behaving correctly - how to avoid missing such errors in unit tests and avoid test bleeding as well, as it seems to be, this type of error manifests only with unannotated test class.
Thank you!
(JUnit4, Spring 4.0.2.RELEASE, Hibernate 4.3.1.Final)
Beacause of the issues mentioned in :
Why not to use Spring's OpenEntityManagerInViewFilter
and
http://heapdump.wordpress.com/2010/04/04/should-i-use-open-session-in-view/
I'd like to use an alternative for Springs OpenentityManagerInViewFilter. This is definitely a performance issue. If I disable the OpenentityManagerInViewFilter I ocassionally get the error:
LazyInitializationException:42 - failed to lazily initialize a collection
One alternative to the filter is to access all of elements in a collection that is lazy loaded before sending them via the request to the view. However, at this point you should question whether these attributes need to be eagerly fetched.
Here is some psuedo code to demonstrate.
//Inside controller
Department dept = dao.findDepartment(id);
//This will load the entities, avoiding the exception.
for(Employee e: dept.getEmployees()){ //Assume employees are lazy loaded
e.getName();
}
request.setAttribute("department", dept); //In Spring this could be the model
I am using Spring 3, JPA + Hibernate for a CMS application. In that application I have a service class method which is annotated with #Transactional Annotation with rollBack property. Inside that method I am inserting data (ie entity classes) to a table using a loop. For each iteration of the loop entity classes has to be saved to the database. But it is not happening. The commit only happens when the execution of the loop has completed and exits from the method. Then it commits and saves all at once. But I need to read data once it gets inserted into the database before committing in this case. I tried with the ISOLATION LEVEL to read uncommitted but it didn't supported since I am using the default JPADialect. Also tried to add the hibernate implementation of jpaDialect but still it didn't worked. Please help with a workaround for this problem. One more thing, is there any way using propagation required method.
You are right, this is what I stands for in acid. Because the transactions are working in isolation, other transactions cannot see them before they are committed. But playing with isolation levels is a bad practice. I would rather advice you to run each and every iteration in a separate transaction with start and commit inside.
This is a bit tricky in Spring, but here is an example:
public void batch() {
for(...) {
insert(...)
}
}
//necessarily in a different class!
#Transactional
public void insert() {
}
Note that batch() is not annotated with #Transactional and insert() has to be in a different class (Spring service). Too long to comment, but that's life. If you don't like it, you can use TransactionTemplate manually.
remove the transactional annoation on the the method with loop.
In the loop call a separate method to perform the save, make that method transactional
You either need to go with programmatic transactions (Spring's TransactionTemplate or PlatformTransactionManager are the classes to look at, see Spring Doc for programmatic transactions, or you can call another transactional method from within your loop where the transaction is marked with Propagation.REQUIRES_NEW, meaning each call of that method is executed in its own transaction, see here. I think that the second approach requires you to define the REQUIRES_NEW method on a different Spring bean because of the AOP-Proxy. You can also omit the REQUIRES_NEW if the loop is not executed within a transaction.