5 Replies Latest reply on Feb 16, 2014 3:24 AM by martin.andersson

    When can I manage deploy and undeploy tasks of a custom deployment

    thilaire

      Hello,

       

      I'm trying to automate the deploy and undeploy task of an unmanaged arquillian deployment.

      That works pretty fine when I do it into @Before and @After steps but I'd like to remove the copy/paste of same lines of my test classes.

       

      What I already tried  is:

       

      - With a jUnit rule

      => NOK, the injection of "@ArquillianResource Deployer" is performed after the rules so I don't have the Deployer at this time

       

      - By overloading the "withBefores" of Arquillian runner

      => NOK, Arquillian executes the @Before with some contexts activated and desactivate them as soon as the @Before ends up.

      So when I do just after the "State.getTestAdaptor().before([...])",  "deployer.deploy(deployment.name())"  it triggers a IllegalArgumentException "No deployment scenario in context" because there is no more ClassContextImpl activated.

       

      - Using Arquillian lifecycle events

      => NOK, I don't find the right event to listen to allow a custom deployment to be done

       

      Anybody has an idea of how can I deploy my archive without copy/paste my @Before and @After in every test classes ?

      Thanks a lot !

        • 1. Re: When can I manage deploy and undeploy tasks of a custom deployment
          ehugonnet

          Create a superclass with also the @RunWith which is also inherited.

          Also you could set the deployer in there.

          Not really pretty but it would 'do the job' and simplify greatly your tests removing the boilerplate code from them.

          Wdyt ?

          • 2. Re: When can I manage deploy and undeploy tasks of a custom deployment
            thilaire

            Thanks Emmanuel, it's what I did temporary and it's work as well.

             

            I finally get it working with an Arquillian extension, here is the extension code  :

             

            public class DeployForEachTestsExtension implements LoadableExtension {
            
               @Override
               public void register(ExtensionBuilder builder) {
                  builder.observer(Handler.class);
               }
            
               public static class Handler {
            
                    public void executeOnJUnitBefore(@Observes Before event, Deployer deployer, TestClass testClass) {
                        Deployment deployment = findRequiredAnnotation(testClass, Deployment.class);
                        if (hasToManage(testClass, deployment)) {
                            deployer.deploy(deployment.name());
                        }
                    }
            
                    public void executeOnJUnitAfter(@Observes After event, Deployer deployer, TestClass testClass) {
                        Deployment deployment = findRequiredAnnotation(testClass, Deployment.class);
                        if (hasToManage(testClass, deployment)) {
                            deployer.undeploy(deployment.name());
                        }
                    }
            
                    private boolean hasToManage(TestClass testClass, Deployment deployment) {
                        return !deployment.managed()
                            && findAnnotation(testClass, DeployForEachTests.class) != null;
                    }
            
                    private <T extends Annotation> T findRequiredAnnotation(TestClass testClass, Class<T> annotation) {
                        Method deploymentMethod = findAnnotation(testClass, annotation);
                        if (deploymentMethod != null) {
                            return deploymentMethod.getAnnotation(annotation);
                        }
                        throw new IllegalStateException(annotation.getName() + " not found in given test class");
                    }
            
                    private <T extends Annotation> Method findAnnotation(TestClass testClass, Class<T> annotation) {
                        return testClass.getMethod(annotation);
                    }
               }
            }
            

             

            And I use it like that (I also created an annotation @DeployForEachTests):

                @DeployForEachTests
                @Deployment(managed=false, name=ARCHIVE) 
                public static WebArchive createDeployment() {
                    return ObmSyncArchiveUtils
                            .buildWebArchive(CalendarBindingImplIntegrationTestModule.class)
                            .addAsResource("sql/org/obm/sync/calendar/h2.sql", H2GuiceServletContextListener.INITIAL_DB_SCRIPT)
                            .addClasses(CalendarBindingImplIntegrationTestModule.class);
                }
            

             

            Thanks to Emmanuel and Aslak for your help !

            • 3. Re: When can I manage deploy and undeploy tasks of a custom deployment
              tommysdk

              I'm curious to hear about your use case for this scenario.

              • 4. Re: When can I manage deploy and undeploy tasks of a custom deployment
                thilaire

                Hello Tommy, as I explained at https://community.jboss.org/message/830724#830724

                 

                Briefly it's to clean the whole webapp state, not only the database, between two tests !

                • 5. Re: When can I manage deploy and undeploy tasks of a custom deployment
                  martin.andersson

                  Yeah I agree and understand your needs. I got them too. I thought Arquillian already did redeploy the test suite for each test case, but as I found out the hard way that isn't the case. Finding out about the Arquillian life cycle through the documentation is kind of hopeless if I may be sincere. I also tried using the Deployer API in my code, did a "deployer.deploy("myAppName")" @Before each test case and a "depoyler.undeploy("myAppName")" @After each test case. That didn't work. At least for GlassFish 4 in managed and embedded mode. So I'm back in the basement scratching my head trying desperately to find a hack.

                   

                  Thomas, you use a reference variable "deployer" in your extension code pasted above. Where does he come from? And why can I not use the Deployer API in my @Before and @After methods? Of course I get a reference to my deployer using @ArquillianResource and I also annotate the deployment like so: @Deployment(managed=false, name="myAppName") but as I said, it refuse to work. And I get all kinds of error messages. It seems to be the case that is is the undeploy() method that doesn't work and next round up GlassFish will complain that the applications is already deployed. After that I get a cocktail of exceptions.