14 Replies Latest reply on Feb 21, 2012 2:53 PM by bmajsak

    How can I clean the DB before each test?

    membersound

      Hi guys,

       

      I'm trying to use Arquillian extension persistence to clean my DB before each test.

      Afaik I can only active the extension by using the annotation @UsingDataSet?

       

      If so, I tried a @UsingDataSet("empty.yml") before each test method, which should then clean my DB.

      Unfortunatelly it has no effect. Am I missing something, or could you point me to the right direction cleaning the db?

       

      Thans a lot

       

       

      @RunWith(Arquillian.class)
      public class FacadeTest {
         @Deployment
         public static Archive<?> createTestArchive() {
            return ShrinkWrap.create(WebArchive.class, "test.war")
                  .addClasses(MyClass.class)
                  .addAsResource("META-INF/persistence.xml", "META-INF/persistence.xml")
                  .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
      } 
      
      @Inject
      Facade facade;
      
      @Test
      @UsingDataSet("empty.yml")
      public void shouldDoSomething() {
      //...
      }
      
      }
      
        • 1. Re: How can I clean the DB before each test?
          bmajsak

          Hi David,

           

          As currently implemented (Alpha3 version), cleanup event should be fired after each test execution, not before. So if you have some data in the database before your very first test is executed it will be there. To be honest I started with the assumption that empty database will be used for testing. But actually we can fire cleanup event before applying datasets - something to consider. Thanks for the suggestion!

           

          If you want to clean your db before the test execution there is another way - by using custom SQL provided by @UsingScript.

           

          With regards to activating the extension you can use @UsingDataSet, @ShouldMatchDataSet, @UsingScript or @Transactional. There is also @PersistenceTest annotation which you can use on the class level - sort of marker annotation which will make all your tests transactional. So for now there is bunch of options as you can see

           

          HTH

           

          Cheers,

          Bartosz

          • 2. Re: How can I clean the DB before each test?
            membersound

            Thanks, @PersistenceTest was the kind I was looking for.

             

            Anyhow I'm confused about the DB cleanup: does Arquillian do a DB clean automatically before or after each @Test annotated method? That is what I assumed, but what does not take place. Therefore I tried to configure those "empty" datasets. Which do not work either.

             

            Which is really strange, bc I'm just doing some crud, and it already works in the browser as app.

            Going kinda crazy why the db is not clean before each test...

             

             

            @Test
            public void shouldCreateSingleCustomer() {
                Customer c = facade.getNewCustomer();
                c.setName("John");
                facade.persistCustomer();
                assertNotNull(c.getId());
            }
            
            //serveral other methods
            
            @Test
            public void shouldDeleteCustomer() {
                Customer c = facade.getCustomer();
                facade.persistCustomer();
                facade.delete(c);
                assertTrue(facade.getCustomers().isEmpty()); //<--- often fails, dependent on the order other test methods are executed
            }
            
             //customer facade kinda looks like this
            class Facade() {
                private Customer customer;
                private List<Customer> customers;
            
                @Inject
                Service service;
            
                public persistCustomer() {
                    service.persist(customer);
                    customers.add(customer);
                }
            
                public deleteCustomer() {
                    service.delete(customer);
                    customers.remove(customer);
                }
            }
            
            • 3. Re: How can I clean the DB before each test?
              bmajsak

              DB cleanup is performed after each @Test. Using empty dataset will simply add "empty set" of data - meaning your db will remain unchanged.

              • 4. Re: How can I clean the DB before each test?
                membersound

                Ok so empty dataset is not the right way to go.

                Could I have accidentially have disabled the cleanup?

                 

                Or maybe it is important to mention the DB that I'm using:

                      <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>

                 

                Is there anything special about it?

                 

                 

                Just to make sure: Annotation this way is sufficient to make the auto-cleanup work?:

                 

                @RunWith(Arquillian.class)
                @PersistenceTest
                public class FacadeTest {
                
                • 5. Re: How can I clean the DB before each test?
                  bmajsak

                  If you enabled persistence extension by using any of the annotations mentioned above cleanup event should be fired for every test. Could you please paste here your arquillian.xml ?

                   

                  Currently you need to point persistence extension to the datasource you are using, defining it for instance in arquillian.xml

                   

                  {code:xml}<extension qualifier="persistence">

                      <property name="defaultDataSource">java:jboss/datasources/ExampleDS</property>

                      <property name="userTransactionJndi">java:jboss/UserTransaction</property>

                  </extension>

                  {code}

                   

                  • 6. Re: How can I clean the DB before each test?
                    membersound
                    <?xml version="1.0" encoding="UTF-8"?>
                    <arquillian xmlns="http://jboss.org/schema/arquillian"
                       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                       xsi:schemaLocation="http://jboss.org/schema/arquillian
                            http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
                    
                       <!-- Force the use of the Servlet 3.0 protocol with all containers, as it is the most mature -->
                       <defaultProtocol type="Servlet 3.0" />
                    
                       <!-- Example configuration for a remote JBoss AS 7 instance -->
                       <container qualifier="jboss" default="true">
                          <!-- If you want to use the JBOSS_HOME environment variable, just delete the jbossHome property -->
                          <configuration>
                             <property name="jbossHome">/Users/JohnDoe/servers/jboss-as-web-7.0.2.Final</property>
                          </configuration>
                       </container>
                    </arquillian>
                    

                     

                     

                    <?xml version="1.0" encoding="UTF-8"?>
                    <persistence version="2.0"
                       xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                       xsi:schemaLocation="
                            http://java.sun.com/xml/ns/persistence
                            http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
                       <persistence-unit name="primary">
                          <!-- If you are running in a production environment, add a managed 
                             data source, the example data source is just for proofs of concept! -->
                          <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
                          <properties>
                             <!-- Properties for Hibernate -->
                             <property name="hibernate.hbm2ddl.auto" value="create-drop" />
                             <property name="hibernate.show_sql" value="false" />
                          </properties>
                       </persistence-unit>
                    </persistence>
                    
                    • 7. Re: How can I clean the DB before each test?
                      bmajsak

                      Please try to add <extension> part which I pasted above.

                       

                      But it's quite strange that it's not complaining that data source is not specified for the persistence extension. I will investigate this regression.

                       

                      There is also small example of the extension in action - just for reference https://github.com/arquillian/arquillian-showcase/tree/master/jpa-persistence-extension

                      • 8. Re: How can I clean the DB before each test?
                        membersound
                           <extension qualifier="persistence">
                             <property name="defaultDataSource">java:jboss/datasources/ExampleDS</property>
                              <property name="initStatement">SET REFERENTIAL_INTEGRITY FALSE</property>
                             <property name="userTransactionJndi">java:jboss/UserTransaction</property>
                           </extension>
                        

                         

                        Does not work. Behaviour did not change :/

                        • 9. Re: How can I clean the DB before each test?
                          bmajsak

                          Hmm... then I have some interesting case to work on. I'm sorry to hear that it does not work for you.

                           

                          Would you be so kind and isolate this problem so I can reproduce and analyze? Preferably by opening JIRA issue for that (you can attach code there or share it over github)?

                          • 10. Re: How can I clean the DB before each test?
                            membersound

                            Hm yes I will try to strip my project down tomorrow. Thanks for you help so far!

                            • 11. Re: How can I clean the DB before each test?
                              membersound

                              Ok, I noticed my project was based on a maven archetype. So I just tried the archetype itself, and too it failed - no db cleanup between tests.

                               

                              https://issues.jboss.org/browse/ARQ-747

                              • 12. Re: How can I clean the DB before each test?
                                bmajsak

                                Hi David,

                                 

                                thanks a lot for reporting and sharing the code. There is basically one fundamental problem which was causing all the issues - persistence extension wasn't included in your Arquillian tests because you didn't include "implementation" artifact:

                                 

                                 

                                {code:xml}<dependency>

                                  <groupId>org.jboss.arquillian.extension</groupId>

                                  <artifactId>arquillian-persistence-impl</artifactId>

                                  <version>1.0.0.Alpha3</version>

                                </dependency>

                                {code}

                                 

                                This actually make me thinking if the artifacts structure shouldn't be simplified.

                                 

                                So there is not issue with cleaning the database after each test - it works as intended. However, thanks to your specific use case and approach to solve it, you helped me to identify two cases where we have buggy behaviour:

                                 

                                1. When you don't use any data set in the test, but @Transactional or @PersistenceTest, extension is failing to enrich test archive - ARQ-752

                                2. Empty YAML file is not handled properly by DBUnit - ARQ-751

                                 

                                So for the time being please apply following workaround:

                                 

                                1. Add "implementation" to your pom.xml"

                                 

                                2. Use empty XML data set in your test:

                                 

                                {code:java}

                                @RunWith(Arquillian.class)

                                @UsingDataSet("empty.xml")

                                public class MemberRegistrationTest {

                                 

                                   @Deployment

                                   public static Archive<?> createTestArchive() {

                                      return ShrinkWrap.create(WebArchive.class, "test.war")

                                            .addClasses(Member.class, MemberRegistration.class, Resources.class, MemberListProducer.class)

                                            .addAsResource("META-INF/persistence.xml", "META-INF/persistence.xml")

                                            .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");

                                   }

                                 

                                   @Inject

                                   MemberRegistration memberRegistration;

                                 

                                   @Inject

                                   MemberListProducer producer;

                                 

                                   @Inject

                                   Logger log;

                                 

                                   @Test

                                   public void testRegister() throws Exception {

                                      Member newMember = memberRegistration.getNewMember();

                                      newMember.setName("Jane Doe");

                                      newMember.setEmail("jane@mailinator.com");

                                      newMember.setPhoneNumber("2125551234");

                                      memberRegistration.register();

                                      assertNotNull(newMember.getId());

                                      log.info(newMember.getName() + " was persisted with id " + newMember.getId());

                                   }

                                 

                                   @Test

                                   public void testProducerIsEmpty() {

                                      assertTrue(producer.getMembers().isEmpty());

                                   }

                                }

                                {code}

                                 

                                And dataset:

                                {code:xml}<dataset />{code}

                                 

                                I will release Alpha4 soon which will provide fixes to these problems.

                                 

                                Thank you very much for your feedback. Much appreciated!

                                • 13. Re: How can I clean the DB before each test?
                                  membersound

                                  edit: ok, got around some UE with following config. works great now, thnx for you support!

                                   

                                   

                                  <?xml version="1.0" encoding="UTF-8"?>
                                  <arquillian xmlns="http://jboss.org/schema/arquillian"
                                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                     xsi:schemaLocation="http://jboss.org/schema/arquillian
                                          http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
                                  
                                     <!-- Force the use of the Servlet 3.0 protocol with all containers, as it is the most mature -->
                                     <defaultProtocol type="Servlet 3.0" />
                                  
                                     <!-- Example configuration for a remote JBoss AS 7 instance -->
                                     <container qualifier="jbossas-remote-7" default="true">
                                        <!-- If you want to use the JBOSS_HOME environment variable, just delete the jbossHome property -->
                                        <configuration>
                                           <property name="jbossHome">/Users/JohnDoe/servers/jboss-as-web-7.0.2.Final</property>
                                        </configuration>
                                     </container>
                                     
                                     <extension qualifier="persistence">
                                       <property name="defaultDataSource">java:jboss/datasources/ExampleDS</property>
                                        <property name="initStatement">SET REFERENTIAL_INTEGRITY FALSE</property>
                                       <property name="userTransactionJndi">java:jboss/UserTransaction</property>
                                       
                                  </arquillian>
                                  
                                  • 14. Re: How can I clean the DB before each test?
                                    bmajsak

                                    Hi David,

                                     

                                    sorry that I wasn't able to respond earlier - I was offline for a bit. Glad that it works now for you