Monday, June 23, 2014

Java EE7 and Maven project for newbies - part 6 - #jpa2 and Unit testing using #arquillian / #WildflyAs 8.1 #maven #jboss

Series 

    Previous Post, Next Post

    In the previous post (part 5), we discovered how we can unit test using Arquillian, our EJB services, deploying them in a 'real' instance of Wildfly8.1 application server. Extending the previous example we will add some more configuration and code, so that we can add unit tests that involve our JPA2 Entities. Creating, saving and retrieving information from the database is a very fundamental task of many JavaEE applications. We need to make sure that our domain model and the logic coded on top of,  is as much tested as possible. I am going to use the 'simplest' form of configuration and related libraries. Since we already test towards Wildfly 8.1, we will be using an internal H2 in-memory database that is bundled with the server, and the pre-configured ExampleDS datasource

    Watch out, this is just for testing and demo, in real life you will want to test under a  production based RDBMS, so most probably you would be needing:
    • create a test DB schema in your DB server (e.g Oracle, MySQL, DB2...)
    • Add appropriate Datasource configuration to the application server, so that it connects to to the above DB server.
    We have already setup Arquillian, and is already leveraging the capabilities of a standalone Wildfly 8.1 server. In the previous post (part 5), we have been testing a simple Stateless EJB, that was not retrieving or saving information on the database. On the sample-domain module we have already defined a simple JPA2 Entity Bean. We would like to test some basic stuff, like save the entity on a database, retrieving the entity etc. It is a common pattern even nowdays, for many projects, to create stateless sessions beans that are actually implementing this code for each entity. You might have heard of them as 'DAO' classes. In our case there is no DAO implementation but the same principles would apply.

    Defining a test-persistence.xml

    As we have already defined a standard persistence.xml under the sample-domain module (jar), that is configuring actually our Entity Manager, we need a similar confinguration. Eventually a very similar persistence xml but this time is going to be placed in the /src/test/resources folder, because it is going to cofigure for us, an Entity Manager that is going to be picked during our tests, from our Arquillian/Wildfly test combo.



    This how it looks

    Some notes on the above file


    • We are defining the ExampleDatasource that is pre-configured on Wildly 8.1
    • WildFly 8.1 comes bundled with Hibernate 4.x, so we are using 'safely' properties of Hibernate configuration.
    • We are using the 'create-drop' strategy so that means that every time we run the test (s), hibernate is going to drop the tables in the underlying database and recreate them. That will help us in cases where we are experimenting and we are constantly changing our domain model.  
    • The emb. database that Wildly offers is H2, so we are configuring Hibernate to use this 'dialect'.

    Creating an Arquillian Test

    This is how our test look like (you can check out the source, on the git link at the end of the post)



    Some notes on the above code

    Point 0: This is one of the most important parts of every Arquillian based test. This is where we create the in memory  'war', our deploy-able that will contain the classes under test and any other resources needed by the supporting frameworks. All the wiring is done using an Arquillian based framework called ShrinkWrap. In our case the 'createDeployment' method, will package our single JPA entity called 'User' and a persistence.xml file, which is actually the test-persistence.xml under our test resources , configuring an Entity Manager that is working with the default Wildly Datasource. 

    Point 1: This is a special annotation, very handy on more complex tests, by using this annotation we are actually injecting by default JTA (transactional) support on our test methods, in this particular test is not heavy used. Make note of the ROLLBACK setting. It indicates that whatever this test method does within a transaction at the end all the insertions/deletes/updates are going to be rollbacked, so we leave no garbage behind.

    Point 2:We need to annotate our test with the appropriate RunWith annotation, indicating that we want the Junit/Arquillian mechanism enabled

    Point 3: We are injecting an entity manager, like we would have done in a regular EJB /resource. The name of the persistence manager must much with the one defined in the test-persistence.xml , so watch out.

    Point 4: The @Before Annotation is indicating that the init() method, will run before every test. This is a great place to initialize any data,and prepare our test domain environment.

    Point 5: As you can see within the init() method, we are persisting a User entity, similar to what we would have done in our product / real code!

    Point 6: The actual test method, we are trying to query for the object, persisted later on.

    Finally

    The fact that we have already configured and prepared our project structure and configuration in order to use Arquillian, is actually the most important thing. Once you have the basic blocks ready, then it is a matter of writting more test and experimenting with your code. Right click on the test and as you can see , we have the green light of succes, a clear pass. Happy testing!



    You can find the complete code for this post under the post6 tag on my bitbucket repository.

    Move on to Part 7?

    10 comments:

    1. Hey, although I was following your Java EE 7 tutorial, I have several issues I thought you can help me with.
      While trying to package everything (m2eclipse) I get errors that directory where wildfly should have been downloaded to, does not exist "modulePath \target\wildfly-8.1.0.Final\modules must exist. The strange thing is that when I'm running just a simple test, it works, but no wildfly folder is created under the target dir.

      I would appreciate your help,

      ReplyDelete
      Replies
      1. This comment has been removed by the author.

        Delete
      2. Hi the problem is that, the Eclipse Maven integration is not following 100% the Maven lifecycle, meaning that when eclipse use's it;s internal engine of Maven, for the same pom , it ignores some phases (steps to execute). Some of the them are related with property reading and parsing. If you try to execute the project through command line, and use maven commands, it will work. In order to make such an example work,through eclipse, you will need to add to the parent pom, a special maven plugin for M2e t(this is the eclipse maven integration engine) that instructs eclipse to execute the steps that ignores.

        Have a look : http://tinypic.com/view.php?pic=2qb6nw2&s=8#.VGmiTdZCXrc

        Delete
      3. seems that it does not work even with when I'm running maven from the cmd (Sorry for the double post =) )

        Delete
      4. (and the typo)

        Delete
      5. Never mind I was stupid enough not to notice that everything was under pluginManagement.
        Thnx!!

        Delete
    2. seems that it does not work even with when I'm running maven from the cmd

      ReplyDelete
    3. This comment has been removed by a blog administrator.

      ReplyDelete
    4. Hi papo, May I know why the unit test for domain object (DTO) is tested in service layer, and not in sample-domain itself?

      ReplyDelete
      Replies
      1. Valid comment. To be honest, since it is the 'model' of the service layer, it was close there. But then again, you are right.

        Delete