Testing a JMX Portable Extension for CDI
germanescobar Feb 28, 2010 8:23 AMHere 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-SNAPSHOT</version> <scope>test</scope> </dependency> ...
Then, I created two profiles on my pom.xml: one for JBoss AS 6.0.0.M1 and other for the Weld-SE (testing inside other containers is just a matter of creating more profiles):
<profiles> <profile> <id>jboss-remote-60</id> <dependencies> <dependency> <groupId>org.jboss.arquillian</groupId> <artifactId>arquillian-jboss-remote-60</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> </dependencies> </profile> <profile> <id>weld-se</id> <dependencies> <dependency> <groupId>org.jboss.arquillian</groupId> <artifactId>arquillian-weld-embedded</artifactId> <version>1.0.0-SNAPSHOT</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:
- The class must extend org.jboss.arquillian.testng.Arquillian.
- 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 -Pjboss-remote-60
- mvn clean install -Pweld-se
Note: JBoss AS 6.0.0.M1 must be running if you are using the -Pjboss-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!