Unit Testing EJB is something that not everyone needs. EJB is so much container managed, and has been around for a long time. But no one can skip the Unit Testing.
Let me discuss a scenario(/ an architecture), where unit testing is nightmare.
In my recent project, its SOA based architecture, and each EJB going into its own .ear file. Right now, around 150 .ear files. On a new requirement, there are 10-12 new EJB's and all having huge amount of changes, and lot of cuntionality. Complication is they are very much interdependent, and all are going to be exposed as Web Services, and there is an Integration layer over these EJB's.
Now, Imagine you are working on a new component( an EJB session bean), which is dependent on other 8-9 EJB's, which are in different EAR's, of which most are not developed. Some are EJB 2.1, and some are EJB 3.0, many new tables( and entities). And similar case is with all other developers.
With EJB3Unit, you can design a framework for such circumstances.
We all know that Unit test cases are written befor the actual development starts.
So, if there are 8 developers woking on 8 new components, and all are interdependent. They can start using the EJB3Unit framework.
Each developer starts with wriring the EJB interface, and a implementation class with hard coded response(which makes sense), and write a Unit test class for the EJB, in a common project.
And anyone developing its own component first can test its own components.
Because there are mocks for all component, which are not developed yet.
Best thing is we dont need Application Server. And we dont need to alter the common build prematurely.
Apart from that what we can do using the EJB3Unit:
Starting with EJB3UNIT is very simple. As with most of the open source project, EJB3UNIT also comes with a sample project which can be download and imported into IDE.
For new ones to Java/J2EE, it might be difficult to understand the sample project.
There can be another way, I am going to explain how to start working with EJB3UNIT, without using Sample project.
I am using Eclipse 3.6.1, and I also tested on RAD 7.5.
I am going to create a Sample project named: EJB3UnitUsage.
I have create few source folders:
src/main/java - to hold my java classes, i.e. session and entity beans.
src/test/java - to hold the Unit Test Classes
src/test/resources - to hold the properties file.
If you are wondering, what is the contet of properties file.
Actually I just copied them from the downloaded Sample project from the EJB3UNIT site.
And we only need two properties file right now:
ejb3unit.properties, and log4j.properties
It would be better if you follow the same or similar structure.
Below is the screen shot of the package structure and the classes:
MyEntity is my Entity bean
MyInterface is my Session bean Interface.
(Local Interface, It wont make any difference if you make it Remote also).
MySessionBean is my Session Bean.
Below is the coe for MySessionBean:
I have injected the EntityManager and I can use it also.
We would test if at runtime it is null or not, and also what the operation "getName()" returns at runtime.
Below is my Test class:
Advanced:
There would be cases, when there is already a project with entities.
We can import those entities, and persistence.xml, in our framework.
For eg, I created a sample project with three entities, and persistence.xml.
I exported the java classes as jar file, and imported the jar file into my project, i.e. "EJB3UnitUsage".
I added the persistence.xml to the "EJB3UnitUsage" project.
Now, I am going to perform some operations over the imported entities.
Inside my session bean, I write code to persist the Book entity, and then find it later.
Our framework is using In mememory database, and so entity would be persisted there.
Also, we need to add following properties in the "ejb3unit.properties":
#Configuration for Persistence classes
ejb3unit.loadPersistenceXML=true
ejb3unit.persistenceUnit.name=mgr
Remember, "mgr" is the name of persistence-unit defiend in the persistence.xml.
Now, when we would run our test case, the persistence.xml, would be read, and also the persistence-unit, and entities would be loaded in memory.
Note the path of persistence.xml, it should in class path. I placed it inside the META-INF.
I have added following code in my Session Bean:
And inside my the test class I add code for testing the entity operation:
I have also tested Entities with @OneToMany, and @ManyToOne relations.
They also work.
I dont know why ArrayList doesn't work in the case of @OneToMany. List works, and Collection works.
For eg., below is the raltion between two entities:
And my code of Lesson.java looks like:
Let me discuss a scenario(/ an architecture), where unit testing is nightmare.
In my recent project, its SOA based architecture, and each EJB going into its own .ear file. Right now, around 150 .ear files. On a new requirement, there are 10-12 new EJB's and all having huge amount of changes, and lot of cuntionality. Complication is they are very much interdependent, and all are going to be exposed as Web Services, and there is an Integration layer over these EJB's.
Now, Imagine you are working on a new component( an EJB session bean), which is dependent on other 8-9 EJB's, which are in different EAR's, of which most are not developed. Some are EJB 2.1, and some are EJB 3.0, many new tables( and entities). And similar case is with all other developers.
With EJB3Unit, you can design a framework for such circumstances.
We all know that Unit test cases are written befor the actual development starts.
So, if there are 8 developers woking on 8 new components, and all are interdependent. They can start using the EJB3Unit framework.
Each developer starts with wriring the EJB interface, and a implementation class with hard coded response(which makes sense), and write a Unit test class for the EJB, in a common project.
And anyone developing its own component first can test its own components.
Because there are mocks for all component, which are not developed yet.
Best thing is we dont need Application Server. And we dont need to alter the common build prematurely.
Apart from that what we can do using the EJB3Unit:
- Dependency Injection(@Resource, @PersistenceContext, etc.)
- Entities and Queries over entities( EJB3UNIT comes with In memory database).
- Component Interdependancy( EJB injection)
- Automated JUNIT test cases.
Starting with EJB3UNIT is very simple. As with most of the open source project, EJB3UNIT also comes with a sample project which can be download and imported into IDE.
For new ones to Java/J2EE, it might be difficult to understand the sample project.
There can be another way, I am going to explain how to start working with EJB3UNIT, without using Sample project.
I am using Eclipse 3.6.1, and I also tested on RAD 7.5.
I am going to create a Sample project named: EJB3UnitUsage.
I have create few source folders:
src/main/java - to hold my java classes, i.e. session and entity beans.
src/test/java - to hold the Unit Test Classes
src/test/resources - to hold the properties file.
If you are wondering, what is the contet of properties file.
Actually I just copied them from the downloaded Sample project from the EJB3UNIT site.
And we only need two properties file right now:
ejb3unit.properties, and log4j.properties
It would be better if you follow the same or similar structure.
Below is the screen shot of the package structure and the classes:
MyEntity is my Entity bean
MyInterface is my Session bean Interface.
(Local Interface, It wont make any difference if you make it Remote also).
MySessionBean is my Session Bean.
Below is the coe for MySessionBean:
I have injected the EntityManager and I can use it also.
We would test if at runtime it is null or not, and also what the operation "getName()" returns at runtime.
Below is my Test class:
Advanced:
There would be cases, when there is already a project with entities.
We can import those entities, and persistence.xml, in our framework.
For eg, I created a sample project with three entities, and persistence.xml.
I exported the java classes as jar file, and imported the jar file into my project, i.e. "EJB3UnitUsage".
I added the persistence.xml to the "EJB3UnitUsage" project.
Now, I am going to perform some operations over the imported entities.
Inside my session bean, I write code to persist the Book entity, and then find it later.
Our framework is using In mememory database, and so entity would be persisted there.
Also, we need to add following properties in the "ejb3unit.properties":
#Configuration for Persistence classes
ejb3unit.loadPersistenceXML=true
ejb3unit.persistenceUnit.name=mgr
Remember, "mgr" is the name of persistence-unit defiend in the persistence.xml.
Now, when we would run our test case, the persistence.xml, would be read, and also the persistence-unit, and entities would be loaded in memory.
Note the path of persistence.xml, it should in class path. I placed it inside the META-INF.
I have added following code in my Session Bean:
And inside my the test class I add code for testing the entity operation:
I have also tested Entities with @OneToMany, and @ManyToOne relations.
They also work.
I dont know why ArrayList doesn't work in the case of @OneToMany. List works, and Collection works.
For eg., below is the raltion between two entities:
And my code of Lesson.java looks like:
And in my Session EJB I added code to perform some operations over these related entities: