Enterprise Java Development@TOPIC@
This chapter will create a JUnit test case that will instantiate an EntityManager, perform some basic operations, and log information about the tests.
`-- src `-- test |-- java | `-- myorg | `-- entitymgrex | `-- EntityMgrTest.java `-- resources `-- log4j.xml
Create a JUnit test case to hold your test code. The following is an example of a 4.x JUnit test case that uses @Annotations.
# src/test/java/myorg/entitymgrex/EntityMgrTest.java
package myorg.entitymgrex;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class EntityMgrTest {
private static final Logger log = LoggerFactory.getLogger(EntityMgrTest.class);
@Test
public void testTemplate() {
logger.info("testTemplate");
}
}
Provide a setUpClass() method that runs once before all tests that can create the entity manager. This method must be static.
private static final String PERSISTENCE_UNIT = "entityMgrEx";
private static EntityManagerFactory emf;
@BeforeClass
public static void setUpClass() {
log.debug("creating entity manager factory");
emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT);
}
Provide a setUp() method that will be called before each testMethod is executed. Have this method create an entity manager for the tests to use.
private EntityManager em;
@Before
public void setUp() throws Exception {
log.debug("creating entity manager");
em = emf.createEntityManager();
//cleanup();
}
Provide a tearDown() method that will be called after each testMethod. Have this flush all remaining items in the persistence context to the database and close the entity manager.
@After
public void tearDown() throws Exception {
if (em!=null) {
logger.debug("tearDown() started, em={}", em);
em.getTransaction().begin();
em.flush();
//logAutos();
em.getTransaction().commit();
em.close();
logger.debug("tearDown() complete, em={}", em);
em=null;
}
}
Provide a tearDownClass() method that will be called after all testMethods have completed. This method must be static and should close the entity manager factory.
@AfterClass
public static void tearDownClass() {
if (emf!=null) {
logger.debug("closing entity manager factory");
emf.close();
emf=null;
}
}
Add in a logAutos() method to query and print all autos in the database. Do this after flushing the entity manager in the tearDown() method so you can see the changes from the previous test. The following example uses the entity manager to create an ad-hoc EJB-QL statement.
@After
public void tearDown() throws Exception {
...
em.flush();
logAutos();
em.getTransaction().commit();
...
}
public void logAutos() {
Query query = em.createQuery("select a from Auto as a");
for (Object o: query.getResultList()) {
logger.info("EM_AUTO: {}", o);
}
}
You might also want to add a cleanup() to clear out the Auto table between tests. The example below uses the entity manager to create a native SQL statement.
@Before
public void setUp() throws Exception {
...
em = emf.createEntityManager();
cleanup();
}
public void cleanup() {
em.getTransaction().begin();
Query query = em.createNativeQuery("delete from EM_AUTO");
int rows = query.executeUpdate();
em.getTransaction().commit();
logger.info("removed {} rows", rows);
}
Add a log4j.xml file to src/test/resources that has your desired settings. The one below produces less timestamp information at the console and more details in the logfile.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration
xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="false">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="(%F:%M:%L) -%m%n"/>
</layout>
</appender>
<appender name="logfile" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="target/log4j-out.txt"/>
<param name="Append" value="false"/>
<param name="MaxFileSize" value="100KB"/>
<param name="MaxBackupIndex" value="1"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%-5p %d{dd-MM HH:mm:ss,SSS} [%c] (%F:%M:%L) -%m%n"/>
</layout>
</appender>
<logger name="myorg">
<level value="debug"/>
<appender-ref ref="logfile"/>
</logger>
<root>
<priority value="fatal"/>
<appender-ref ref="CONSOLE"/>
</root>
</log4j:configuration>
Although it might be a bit entertaining to set the priority of the root appender to debug to see everything the persistence provider has to say, it is quite noisy. Consider changing to root priority to fatal so that a majority of the log statements are yours.
You should be able to build and test your module at this time.
$ mvn clean test Running myorg.entitymgrex.EntityMgrTest (EntityMgrTest.java:setUpClass:25) -creating entity manager factory (EntityMgrTest.java:setUp:31) -creating entity manager Hibernate: delete from EM_AUTO (EntityMgrTest.java:cleanup:58) -removed 0 rows (EntityMgrTest.java:testTemplate:75) -testTemplate (EntityMgrTest.java:tearDown:39) -tearDown() started, em=org.hibernate.ejb.EntityManagerImpl@3e52a475 Hibernate: select auto0_.id as id0_, auto0_.color as color0_, auto0_.make as make0_, auto0_.mileage as mileage0_, auto0_.model as model0_ from EM_AUTO auto0_ (EntityMgrTest.java:tearDown:45) -tearDown() complete, em=org.hibernate.ejb.EntityManagerImpl@3e52a475 (EntityMgrTest.java:tearDownClass:69) -closing entity manager factory Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.337 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 ... [INFO] BUILD SUCCESS
If you tests failed and there is no key information printed, try raising the verbosity for all org.hibernate classes to DEBUG.
# src/test/resources/log4j.xml <logger name="org.hibernate"> <level value="trace"/> <appender-ref ref="logfile"/> </logger>
Check that you have the following artifacts in your project tree.
|-- pom.xml
|-- src
| |-- main
| | |-- java
| | | `-- myorg
| | | `-- entitymgrex
| | | `-- Auto.java
| | `-- resources
| | |-- ddl
| | | |-- emauto_create.ddl
| | | |-- emauto_delete.ddl
| | | |-- emauto_drop.ddl
| | | |-- emauto_tuningadd.ddl
| | | `-- emauto_tuningremove.ddl
| | `-- META-INF
| | `-- persistence.xml
| `-- test
| |-- java
| | `-- myorg
| | `-- entitymgrex
| | `-- EntityMgrTest.java
| `-- resources
| |-- hibernate.properties
| `-- log4j.xml
`-- target
|-- antrun
| `-- build-main.xml
|-- classes
| |-- ddl
| | |-- emauto_create.ddl
| | |-- emauto_delete.ddl
| | |-- emauto_drop.ddl
| | |-- emauto_tuningadd.ddl
| | `-- emauto_tuningremove.ddl
| |-- META-INF
| | `-- persistence.xml
| `-- myorg
| `-- entitymgrex
| `-- Auto.class
|-- generated-sources
| `-- annotations
|-- generated-test-sources
| `-- test-annotations
|-- h2db
| `-- ejava.h2.db
|-- log4j-out.txt
|-- maven-status
| `-- maven-compiler-plugin
| |-- compile
| | `-- default-compile
| | |-- createdFiles.lst
| | `-- inputFiles.lst
| `-- testCompile
| `-- default-testCompile
| |-- createdFiles.lst
| `-- inputFiles.lst
|-- surefire-reports
| |-- myorg.entitymgrex.EntityMgrTest.txt
| `-- TEST-myorg.entitymgrex.EntityMgrTest.xml
`-- test-classes
|-- hibernate.properties
|-- log4j.xml
`-- myorg
`-- entitymgrex
`-- EntityMgrTest.class