14 Replies Latest reply: Feb 21, 2012 2:53 PM by Bartosz Majsak RSS

How can I clean the DB before each test?

david meier Newbie

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?
    Bartosz Majsak Master

    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?
    david meier Newbie

    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?
    Bartosz Majsak Master

    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?
    david meier Newbie

    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?
    Bartosz Majsak Master

    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

     

    <extension qualifier="persistence">
        <property name="defaultDataSource">java:jboss/datasources/ExampleDS</property>
        <property name="userTransactionJndi">java:jboss/UserTransaction</property>
    </extension>
    

     

     

  • 6. Re: How can I clean the DB before each test?
    david meier Newbie
    <?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?
    Bartosz Majsak Master

    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?
    david meier Newbie
       <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?
    Bartosz Majsak Master

    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?
    david meier Newbie

    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?
    david meier Newbie

    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?
    Bartosz Majsak Master

    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:

     

     

    <dependency>
      <groupId>org.jboss.arquillian.extension</groupId>
      <artifactId>arquillian-persistence-impl</artifactId>
      <version>1.0.0.Alpha3</version>
    </dependency>
    

     

     

    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:

     

    @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());
       }
    }
    

     

     

    And dataset:

    <dataset />

     

     

    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?
    david meier Newbie

    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?
    Bartosz Majsak Master

    Hi David,

     

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