Dienstag, 4. Oktober 2011

Testing with Arquillian and Embedded Glassfish 3.1 - Part 2

We are configured our project to create and run tests with Arquillian. Here i will explain how to create a simple test using Arquillian and JPA.

We have created a data source with JNDI-name "jdbc/sample" in part 1, we will use it for our JPA test, i have used an API to make generic DAOs and hibernate-entity-manager as an entitity manager, needed dependencies therefore :

  1. <dependency>
  2.     <groupId>org.hibernate</groupId>
  3.     <artifactId>hibernate-entitymanager</artifactId>
  4.     <version>3.6.7.Final</version>
  5.     <exclusions>
  6.         <exclusion>
  7.             <artifactId>slf4j-api</artifactId>
  8.             <groupId>org.slf4j</groupId>
  9.         </exclusion>
  10.     </exclusions>
  11. </dependency>
  12. <dependency>
  13.     <groupId>org.hibernate</groupId>
  14.     <artifactId>hibernate-core</artifactId>
  15.     <version>3.6.7.Final</version>
  16.     <exclusions>
  17.         <exclusion>
  18.             <artifactId>slf4j-api</artifactId>
  19.             <groupId>org.slf4j</groupId>
  20.         </exclusion>
  21.     </exclusions>
  22. </dependency>
  23. <!-- generic DAO dependencies -->
  24. <!-- This first dependency includes all the JPA implementations for the DAOs -->
  25. <dependency>
  26.     <groupId>com.googlecode.genericdao</groupId>
  27.     <artifactId>dao</artifactId>
  28.     <version>1.0.0</version>
  29. </dependency>
  30. <!-- This second one includes the Hibernate Entity Manager plugin for the framework -->
  31. <dependency>
  32.     <groupId>com.googlecode.genericdao</groupId>
  33.     <artifactId>search-jpa-hibernate</artifactId>
  34.     <version>1.0.0</version>
  35. </dependency>
  36. <!-- end of generic DAO dependencies -->

I've created a BaseDAO interface and then the a specific interface to provide CRUD operations for users.

  1. /**
  2.  * @author Hasan Oezdemir
  3.  * @since 01.10.2011
  4.  *
  5.  */
  6. public interface BaseDAO<T, ID extends Serializable> extends GenericDAO<T, ID> {
  7.     public Collection<T> findByExample(T example);
  8.    
  9.     public T findByExampleUnique(T example);
  10. }

  1. /**
  2.  * @author Hasan Oezdemir
  3.  * @since 01.10.2011
  4.  *
  5.  */
  6. public interface UserDAO extends BaseDAO<User, Long> {
  7. }

And an abstract class for JPA implementations :

  1. /**
  2.  * @author Hasan Oezdemir
  3.  * @since 01.10.2011
  4.  *
  5.  */
  6. public abstract class JPAGenericDAO<T, ID extends Serializable> extends GenericDAOImpl<T, ID> implements
  7.         BaseDAO<T, ID> {
  8.     private static final Logger logger = LoggerFactory.getLogger(JPAGenericDAO.class);
  9.    
  10.     @PersistenceContext(unitName="sample")
  11.     private EntityManager entityManager;
  12.    
  13.     public JPAGenericDAO(){
  14.         super();
  15.     }
  16.    
  17.     @PostConstruct
  18.     public void initialized(){
  19.          this.setEntityManager(entityManager);
  20.         JPASearchProcessor searchProcessor = new JPASearchProcessor(new JPAAnnotationMetadataUtil());
  21.         this.setSearchProcessor(searchProcessor);
  22.     }
  23.     @Override
  24.     public T findByExampleUnique(T example) {
  25.         Search s = this.createSearch(example);
  26.         return searchUnique(s);
  27.     }
  28.     @Override
  29.     public Collection<T> findByExample(T example) {
  30.         Search s = this.createSearch(example);
  31.         return search(s);
  32.     }
  33.    
  34.     protected Search createSearch(T example) {
  35.         Search s = new Search(example.getClass());
  36.         s.addFilter(this._getFilterFromExample(example));
  37.         return s;
  38.     }
  39. }

As you remember we are created a persistence-unit named "sample" while injecting the entity-manager at this point, we are used this unit for our DAOs :
  1. @PersistenceContext(unitName="sample")
  2. private EntityManager entityManager
And a reference implementation for our JPA DAO :


  1. /**
  2.  * @author Hasan Oezdemir
  3.  * @since 01.10.2011
  4.  *
  5.  */
  6. @Singleton
  7. public class JPAUserDAO extends JPAGenericDAO<User, Long> implements UserDAO {
  8.     public JPAUserDAO(){
  9.         super();
  10.     }
  11. }

We are now ready to implement an Arquillian Test for our JPA class.The most important section to create a static method annotated with @Deployment to build a ShrinkWrap, here is a sample method:

  1. /**
  2. * Since Arquillian actually creates JAR files under the covers with
  3. * ShrinkWrap, the @Deployment is your way of controlling what is included
  4. * in that Archive. Note, each class utilized in your test case - whether
  5. * directly or indirectly - must be added to the deployment archive.
  6. */
  7. @Deployment
  8. public static Archive<?> createTestArchive() {
  9.     return ShrinkWrap
  10.         .create(JavaArchive.class, "test.jar")
  11.         .addAsResource("arquillian.xml")
  12.         .addPackages(true, UserDAO.class.getPackage())
  13.         .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")
  14.         .addAsManifestResource("META-INF/persistence.xml",
  15.         ArchivePaths.create("persistence.xml"));
  16. }

We must add our arquillian configuration too, otherwise ShrinkWrap reads the default configuration and ignores our configuration.

I've created an abstract class which is extended by all test-classes :


  1. /**
  2.  *
  3.  * @author Hasan Oezdemir
  4.  * @since 02.10.2011
  5.  *
  6.  */
  7. public class AbstractJPATest {
  8.     /**
  9.      * Since Arquillian actually creates JAR files under the covers with
  10.      * ShrinkWrap, the @Deployment is your way of controlling what is included
  11.      * in that Archive. Note, each class utilized in your test case - whether
  12.      * directly or indirectly - must be added to the deployment archive.
  13.      */
  14.     @Deployment
  15.     public static Archive<?> createTestArchive() {
  16.         return ShrinkWrap
  17.                 .create(JavaArchive.class, "test.jar")
  18.                 .addAsResource("arquillian.xml")
  19.                 .addAsResource("log4j.xml")
  20.                 .addPackages(true, UserDAO.class.getPackage())
  21.                 .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")
  22.                 .addAsManifestResource("META-INF/persistence.xml",
  23.                         ArchivePaths.create("persistence.xml"));
  24.     }
  25.     @Inject
  26.     protected UserTransaction userTransaction;
  27.     public AbstractJPATest() {
  28.         super();
  29.     }
  30.     /**
  31.      * @throws java.lang.Exception
  32.      */
  33.     @Before
  34.     public void setUp() throws Exception {
  35.         this.userTransaction.begin();
  36.     }
  37.     /**
  38.      * @throws java.lang.Exception
  39.      */
  40.     @After
  41.     public void tearDown() throws Exception {
  42.         try {
  43.             this.userTransaction.rollback();
  44.         } catch (Exception e) {
  45.             throw new Exception(e);
  46.         }
  47.     }
  48.     /**
  49.      * @return a test user.
  50.      */
  51.     protected User createUser() {
  52.         User user = new User();
  53.         user.setEmail("hasan@hotmail.com");
  54.         user.setName("hasan");
  55.         user.setPassword("12345");
  56.         return user;
  57.     }
  58. }

Transaction management may be better but this is enought for now :)

We must run our tests with Arquillian.class therefore we should add @RunWith(Arquillian.class) for each our tests-classes, here is a sample :


  1. /**
  2.  * @author Hasan Oezdemir
  3.  * @since 01.10.2011
  4.  *
  5.  */
  6. @RunWith(Arquillian.class)
  7. public class JPAUserDAOTest extends AbstractJPATest {
  8.    
  9.     @Inject
  10.     private JPAUserDAO jpaUserDAO;
  11.     /**
  12.      * Test method for
  13.      * {@link com.citecompany.dao.jpa.JPAGenericDAO#findByExampleUnique(java.lang.Object)}
  14.      * .
  15.      */
  16.     @Test
  17.     public void testFindByExampleUnique() {
  18.         User user = this.createUser();
  19.         this.jpaUserDAO.save(user);
  20.         User found = this.jpaUserDAO.findByExampleUnique(user);
  21.         assertNotNull("Expected user " + user + " is not found in data source.", found);
  22.         assertEquals(user.getName(), found.getName());
  23.     }
  24. }

So our test class is ready to start, you start it either with maven or in eclipse.



Keine Kommentare:

Kommentar veröffentlichen