Testing a JMX Portable Extension for CDI

(written by German Escobar)

 

Here is how I used Arquillian to test a simple JMX Portable Extension that I wrote a few weeks ago. The extension allows you to automatically register MBeans using annotations. For example:

 

 

@ApplicationScoped
@MBean("org.gescobar:type=VisitorCounter")
@Description("Counts the number of visits")
public class VisitorCounter {  
  
  @ManagedAttribute(readable=true,writable=true)  
  private int counter;  
  
  public void addVisitor() {    
    counter++;  
  }  

  @ManagedOperation(impact=Impact.ACTION)  
  public void resetCounter() {    
    counter = 0;  
  }  

  // getter and setters
}

 

 

When the bean is instantiated, it will be automatically registered as an MBean on an MBeanServer. You can check my full post on this extension here.

 

After I finished writing the extension, I needed a way of testing it on different containers. So, I decided to try Arquillian.

 

First, I added TestNG and Arquillian dependencies to my pom.xml file (I could also have used JUnit):

 

  ...
  <dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>5.10</version>
    <classifier>jdk15</classifier>
    <scope>test</scope>
  </dependency>

  <dependency>
    <groupId>org.jboss.arquillian</groupId>
    <artifactId>arquillian-testng</artifactId>
    <version>1.0.0.Alpha1</version>
    <scope>test</scope>
  </dependency>
  ...

 

Then, I created two profiles on my pom.xml: one for JBoss AS 6.0.0.M2 and other for the Weld-SE (testing inside other containers is just a matter of creating more profiles):

 

  <profiles>
    <profile>
      <id>jbossas-remote-60</id>
      <dependencies>
        <dependency>
          <groupId>org.jboss.arquillian.container</groupId>
         <artifactId>arquillian-jbossas-remote-60</artifactId>
         <version>1.0.0.Alpha1</version>
        </dependency>
      </dependencies>
    </profile>
    <profile>
      <id>weld-embedded</id>
      <dependencies>
        <dependency>
         <groupId>org.jboss.arquillian.container</groupId>
         <artifactId>arquillian-weld-embedded</artifactId>
         <version>1.0.0.Alpha1</version>
        </dependency>
      </dependencies>
    </profile>
  </profiles>

 

Finally, I wrote my test class. The only two things you need to add to your regular TestNG class are:

 

  1. The class must extend org.jboss.arquillian.testng.Arquillian.
  2. Create a method annotated with @Deployment that returns a Shrinwrap Archive.

 

public class TestAutoRegistration extends Arquillian { 

    @Deployment
    public static JavaArchive createDeployment() {
     
     JavaArchive archive = Archives.create("test.jar", JavaArchive.class)
          .addPackage(MBeanFactory.class.getPackage()) 
          .addPackage(CDIMBeanFactory.class.getPackage())
          .addPackage(MBeanServerLocator.class.getPackage())
          .addClasses(CounterAutoRegisterWithName.class, CounterAutoRegisterNoName.class)
          .addManifestResource("services/javax.enterprise.inject.spi.Extension")
          .addManifestResource(
               new ByteArrayAsset("<beans/>".getBytes()), 
                          Paths.create("beans.xml"));
     
     return archive;
    }

    @Inject
    private CounterAutoRegisterWithName counterWithName;

    @Inject
    private CounterAutoRegisterNoName counterNoName;

    @Test
    public void shouldRegisterAnnotatedWithNameMBean() throws Exception {
     Assert.assertNotNull(counterWithName);
     
     // the bean is not created until the first call - maybe a bug in weld?
     Assert.assertEquals(counterWithName.getCounter(), 0);
     
     MBeanServer mBeanServer = MBeanServerLocator.instance().getmBeanServer();
     ObjectName name = new ObjectName("org.gescobar:type=CounterAutoRegisterWithName");
     
     // check we can add the counter
     mBeanServer.setAttribute(name, new Attribute("counter", 1));
     Assert.assertEquals(counterWithName.getCounter(), 1);
     
     // check we can retrieve the counter
     Integer result = (Integer) mBeanServer.getAttribute(name, "counter");
     Assert.assertNotNull(result);
     
     // check we can call method without arguments
     mBeanServer.invoke(name, "resetCounter", null, null);
     Assert.assertEquals(counterWithName.getCounter(), 0);
     
     // check we can call method with arguments
     mBeanServer.invoke(name, "resetCounter2", new Object[] { 5 }, new String[] { "java.lang.Integer" });
     Assert.assertEquals(counterWithName.getCounter(), 5);
    }

    @Test
    public void shouldRegisterAnnotatedWithNoNameMBean() throws Exception {
     Assert.assertNotNull(counterNoName);
     
     Assert.assertEquals(counterNoName.getCounter(), 0);
     
     MBeanServer mBeanServer = MBeanServerLocator.instance().getmBeanServer();
     Object result = mBeanServer.getAttribute(new ObjectName("org.gescobar.management.test:type=CounterAutoRegisterNoName"), "counter");
     
     Assert.assertNotNull(result);
    }
}

 

Now, to run the tests, I just have to call the appropiate profile:

  • mvn clean install -Pjbossas-remote-60
  • mvn clean install -Pweld-embedded

 

Note: JBoss AS 6.0.0.M2 must be running if you are using the -Pjbossas-remote-60 profile. Arquillian does not start/stop the container automatically ... yet!

 

As you can see, it was really easy to add Arquillian support to my project and now I can test my extension on real containers!


This article was generated from the following thread: Testing a JMX Portable Extension for CDI