7 Replies Latest reply on Sep 21, 2011 8:19 AM by Vineet Reynolds

    How to clean database between tests?

    Viggo Navarsete Expert

      How can I clean the database between tests in a test class when using Arquillian? I don't want to control the transaction management myself (that's part of why I use Arquillian, right..), but I don't want the data put into the database in each test to influence the other tests.

        • 1. Re: How to clean database between tests?
          Vineet Reynolds Apprentice

          You can use @Before, @After JUnit annotations so that you can clean the state of the database between tests. I use DbUnit for resetting the state of the database. I haven't found any Arquillian extension that does something similar, not that I wanted such an extension.

           

          If you want an example, one of my projects does this in an Arquillian driven test; take a look at the @Before method in this class.

          1 of 1 people found this helpful
          • 2. Re: How to clean database between tests?
            Viggo Navarsete Expert

            Thanks Vineet,

             

            I was also thinking about doing it in the @Before and @After annotated methods. The problem/challenge is to do the deletion of data in the tables, while still keeping the tables there for the next test.

            I' ve seen a way of doing it here ("Issue 2 : Clearing the database between tests") http://www.objectpartners.com/2010/11/09/unit-testing-your-persistence-tier-code/ , but it feels a bit cumbersome this way.

             

            I would have hoped for a more "drop and create" kind of way of doing it...

            • 3. Re: How to clean database between tests?
              Vineet Reynolds Apprentice

              I could follow only a few points in your reply. If I understand correctly, you want to delete the data in the tables, without dropping them. DbUnit does that - the CLEAN_INSERT operation DELETEs any data in the tables and INSERTs fresh data from a XML file. With DbUnit, you'll need to worry about the order of the DELETEs, so that the records in the child tables (with foreign keys) are deleted before the parent tables, when foreign key constraints are being enforced.

               

              The section of the article you've referenced demonstrates how to disable referential integrity so that one does not have to worry about the order of the DELETEs. This is a kludge, but a necessary one even with DbUnit, when you have complex relationships across tables (especially foreign keys with circular dependencies).

               

              If you intend to drop and create the tables, even then you'll need to drop the tables in the right order (in most databases). In my opinion, the developer has the knowledge of which tables to drop first, and this ought to reflect in the tests. Automated solutions, especially the ones involving querying of database metadata tend to have their limitations.

              1 of 1 people found this helpful
              • 4. Re: How to clean database between tests?
                Viggo Navarsete Expert

                you might be right about using DBUnit for this purpose. I was initally thinking about doing something similar (or trigger..) what this property would do:

                <property name="hibernate.hbm2ddl.auto" value="create-drop" />

                 

                but that's perhaps not possible, or more expensive than using DBUnit. I will look into you class once more, and try to adapt it if noone else can come up with a better approach:)

                • 5. Re: How to clean database between tests?
                  Vineet Reynolds Apprentice

                  The "create-drop" value for "hibernate.hbm2ddl.auto" will drop and create tables when Hibernate is initialized for the first time.

                   

                  It is more expensive as the Hibernate will now need to be initialized in every test. I don't know how this would be possible, except through creating new classloaders for every test. Also, I suspect that Hibernate wouldn't verify the order of dropping tables (so you would be left with the same problem).

                  • 6. Re: How to clean database between tests?
                    Viggo Navarsete Expert

                    I guess by using manual transaction management like this:

                    EntityManagerFactory emf = Persistence.createEntityManagerFactory( "name_of_persistence_unit" );

                    EntityManager em = emf.createEntityManager();

                    em.getTransaction().begin();

                    ..do stuff

                    ..em.persist(someObject);

                    ..do more stuff

                    ..em.flush();

                    ..em.getTransaction().rollback();

                     

                    would solve the whole problem...but then you're doing stuff that the container shold take care of, so I think I'll end up using DBUnit like you mentioned in the first reply.

                    • 7. Re: How to clean database between tests?
                      Vineet Reynolds Apprentice

                      I started by using EntityTransaction.rollback in one of my other tests, but I found that it is not a good approach. Hibernate creates new transactions in certain events, whose effects cannot be rolled back. In my case, updates of table based sequences would not be rolled back, since Hibernate updates sequences in a separate transaction. If you find that Hibernate does not create new transactions, then you may very well use EntityTransaction.rollback().

                       

                      IMHO, I don't think that this is stuff that a container should take care of. In this case, you are managing the EntityManager and the EntityTransaction, and not the container. The container will manage the EntityManager and the transaction, only when it injects the EntityManager and is responsible for transaction management (CMTs).