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!