Sep 2, 2009
Unit Testing JBoss 5 Services
The JBoss Microcontainer is a refactoring of JBoss’s JMX Microkernel to support direct POJO deployment and standalone use outside the JBoss application server.
It allows the creation of services using simple Plain Old Java Objects (POJOs) to be deployed into a standard Java SE runtime environment.
JBoss Microcontainer uses dependency injection to wire individual POJOs together to create services. Configuration is performed using either annotations or XML depending on where the information is best located.
The goal of this article is to show how easy it is to test these services using TestNG testing framework.
Configuring a service
PersonService is a simple POJO that doesn’t implement any special interfaces.
It has two properties, firstName and lastName, that are inject through a XML deployment descriptor.
The public method that clients will call is getName() and returns the person full name.
public class PersonService { private 1.5.0/docs/api/java/lang/String.html">String firstName; private 1.5.0/docs/api/java/lang/String.html">String lastName; public void setFirstName(1.5.0/docs/api/java/lang/String.html">String firstName) { this.firstName = firstName; } public void setLastName(1.5.0/docs/api/java/lang/String.html">String lastName) { this.lastName = lastName; } public 1.5.0/docs/api/java/lang/String.html">String getName() { return firstName + " " + lastName; } } |
Instances of this service are created by creating an XML deployment descriptor that contains a list of beans representing individual instances.
<?xml version="1.0" encoding="UTF-8"?> <deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:jboss:bean-deployer:2.0 bean-deployer_2_0.xsd" xmlns="urn:jboss:bean-deployer:2.0"> <bean name="PersonService" class="com.samaxes.jboss.service.plain.PersonService"> <property name="firstName">Samuel</property> <property name="lastName">Santos</property> </bean> </deployment> |
We have just declared that we want to create an instance of the PersonService class and register it with the name PersonService. This file is passed to an XML deployer associated with the microcontainer at runtime to perform the actual deployment and instantiate the beans.
Testing a service
JBoss Microcontainer makes it extremely easy to unit test services.
First, you need to create an EmbeddedBootstrap class and override the protected bootstrap() method.
This allows you to created an instance of JBoss Microcontainer together with an XML deployer.
public class EmbeddedBootstrap extends BasicBootstrap { protected BasicXMLDeployer deployer; public EmbeddedBootstrap() throws 1.5.0/docs/api/java/lang/Exception.html">Exception { super(); } public void bootstrap() throws 1.5.0/docs/api/java/lang/Throwable.html">Throwable { super.bootstrap(); deployer = new BasicXMLDeployer(getKernel()); 1.5.0/docs/api/java/lang/Runtime.html">Runtime.getRuntime().addShutdownHook(new Shutdown()); } public void deploy(1.5.0/docs/api/java/net/URL.html">URL url) { try { // Workaround the fact that the BasicXMLDeployer does not handle redeployment correctly if (deployer.getDeploymentNames().contains(url.toString())) { log.info("Service is already deployed."); return; } deployer.deploy(url); } catch (1.5.0/docs/api/java/lang/Throwable.html">Throwable t) { log.warn("Error during deployment: " + url, t); } } public void undeploy(1.5.0/docs/api/java/net/URL.html">URL url) { if (!deployer.getDeploymentNames().contains(url.toString())) { log.info("Service is already undeployed."); return; } try { deployer.undeploy(url); } catch (1.5.0/docs/api/java/lang/Throwable.html">Throwable t) { log.warn("Error during undeployment: " + url, t); } } protected class Shutdown extends 1.5.0/docs/api/java/lang/Thread.html">Thread { public void run() { log.info("Shutting down"); deployer.shutdown(); } } } |
Next, you need to bootstrap the microcontainer. This is done in BaseTest class.
public class BaseTest<T> { private 1.5.0/docs/api/java/net/URL.html">URL url; private EmbeddedBootstrap bootstrap; private 1.5.0/docs/api/java/awt/image/Kernel.html">Kernel kernel; private KernelController controller; @BeforeSuite public void setUpSuite() throws 1.5.0/docs/api/java/lang/Exception.html">Exception { // Start JBoss Microcontainer bootstrap = new EmbeddedBootstrap(); bootstrap.run(); kernel = bootstrap.getKernel(); controller = kernel.getController(); } @AfterSuite public void tearDownSuite() { } protected void deploy(1.5.0/docs/api/java/lang/String.html">String url) { 1.5.0/docs/api/java/lang/ClassLoader.html">ClassLoader cl = 1.5.0/docs/api/java/lang/Thread.html">Thread.currentThread().getContextClassLoader(); this.url = cl.getResource(url); bootstrap.deploy(cl.getResource(url)); } protected void undeploy() { bootstrap.undeploy(url); } @1.5.0/docs/api/java/lang/SuppressWarnings.html">SuppressWarnings( { "unchecked" }) protected T getService(1.5.0/docs/api/java/lang/String.html">String name) { ControllerContext context = controller.getInstalledContext(name); return (context == null) ? null : (T) context.getTarget(); } } |
All the test classes extend this one, this allows you to run the microcontainer only once before the test suite.
Another benefit is to have all the utility methods used in every test class in a central place.
Now we can proceed to the last part, and that is to deploy the Person service.
public class PersonServiceTest extends BaseTest<PersonService> { private static final 1.5.0/docs/api/java/util/logging/Logger.html">Logger LOGGER = LoggerFactory.getLogger(PersonServiceTest.class); private PersonService service; @BeforeClass public void setUp() { deploy("jboss-beans.xml"); service = getService("PersonService"); } @AfterClass public void tearDown() { undeploy(); } @Test public void getName() { 1.5.0/docs/api/java/lang/String.html">String name = service.getName(); LOGGER.info("Name: {}", name); assertEquals("Samuel Santos", name); } } |
To see it in action, get this example source code and run the Maven command mvn test.
Recent Comments