Over a million developers have joined DZone.
Silver Partner

Roo Add-On Development: Testing XML Configurations

· Java Zone

In the last post, we discussed unit testing Roo add-on code. I feel this is just as vital as testing any other piece of Java code, considering that every time you run the command in the container you literally have to boot it, update the OSGi bundle, and then test. The feedback loop is too long to fix little, annoying bugs like not properly parsing an XML document.

Roo "Advanced add-ons" and Configuration

Let's assume we're not stellar coders. Let's even assume that we aren't the best XML developers. I'm shining a bright line at myself here.

With the CoffeeScript add-on, we want to manipulate the pom.xml file - something we don't need a container to do. Roo uses that good ole' built-in JAXP library (and Apache implementation of course). As Ben Alex would say, "stock standard Java." So, we should be able to easily unit test it.

The CoffeescriptOperationsImpl class - under test!

Last blog we showed you how to test the CoffeescriptCommands object, which delegates calls to the CoffeescriptOperations OSGi bean, which is implemented by the CoffeescriptOperationsImpl class. This is where the add-on's work is being done. So, let's test it.

Setting up the test class and Mockito

Like last time, we need to configure Mockito. We'll assume you've read up on that post and have installed the proper dependencies.

We need to test that our operations code works, and that it calls the proper Roo services. So, let's create our bean under test, and then mock the collaborator:

public class CoffeescriptOperationsImplTest {
  private CoffeescriptOperationsImpl coffeescriptOperations; 

  public void setUp() {
    coffeescriptOperations = new CoffeescriptOperationsImpl();
    coffeescriptOperations.projectOperations = 

Again, we manually create our class under test, and configure our mocks, in keeping with typical unit tests of components. I had to widen the visibility of the projectOperations reference to 'friendly' access - so that this class, which lives in the same package as the code under test, can see it and replace it with a mock.

h2. Reviewing our method under test - setup()

Let's look at our setup method:

public void setup(String coffeeDir, 
                String outputDirectory, boolean bare) {
  String moduleName = projectOperations.getFocusedModuleName();
  Element coffeePluginElement = getCoffeeScriptPluginElement();
  Document document = coffeePluginElement.getOwnerDocument();

  if (bare) {
    addTextElement(document, coffeePluginElement, "bare", "true");
  } else {
    addTextElement(document, coffeePluginElement, "bare", COFFEE_DEFAULT_BARE_SETTING);

  if (coffeeDir != null && coffeeDir.trim().length() > 0) {
    addTextElement(document, coffeePluginElement, "coffeeDir", coffeeDir);
  } else {
    addTextElement(document, coffeePluginElement, "coffeeDir", COFFEE_DEFAULT_SRC_DIRECTORY);

  if (outputDirectory != null && outputDirectory.trim().length() > 0) {
    addTextElement(document, coffeePluginElement, "coffeeOutputDirectory", outputDirectory);
  } else {
    addTextElement(document, coffeePluginElement, "coffeeOutputDirectory", COFFEE_DEFAULT_OUTPUT_DIRECTORY);

  projectOperations.addBuildPlugin(moduleName, new Plugin(coffeePluginElement));

It's clear that we have a LOT of branches in this code, but that's because we're taking input from our command itself. I'll lie here, and tell you that I've written tests against all of these branches, but again, I said I'm lying - and in a further lie, I'll tell you that "I'm gonna get to it!" However, here's why lying doesn't help - I'm sure I have bugs in this code, and I really need to verify it all.

Oh, and I was thinking - I have a few private methods to help me keep the code organized and modular... Perhaps I should test those too but that leads the way of code smell... Interesting read BTW.

Reviewing the tasks in the method

Ok, the method does a few things:

1. Asks a helper method for the Configuration XML file as a basis for the Maven plugin.
2. Does a couple of gyrations so that we can maniuplate the plugin nodes with the DOM API - since Roo's Maven object model is essentially a thin wrapper around the XML API we have to think more in XML. This is something I'll be exploring in the future.
3. Sets the options the user passed in.
4. Adds the build plugin to the Maven build.

Ultimately, though, we need to see if:

1. Given a call to setup(), and the appropriate parameters,
2. Does the Plugin contain the proper information

Our test method for the setup process


public void testSetupCoffeescript() {


  // a way for Mockito to grab passed input parameters for testing
  ArgumentCaptor<Plugin> pluginCaptor = 

  // invoke our method
  coffeescriptOperations.setup("baz", "bar", false);

  // did we call addBuildPlugin? Also, notice we capture what the
  // method passed to the mocked projectOperations.addBuildPlugin method
  // for the plugin XML Element code
     .addBuildPlugin(any(String.class), pluginCaptor.capture());

  // Since the plugin has been called and we've captured the method's 
  // second argument, we'll pluck it out and take a gander...
  Plugin coffeescriptPlugin = pluginCaptor.getValue();

  // make sure they passed something!

  // checks against the model
  Assert.assertEquals("false", coffeescriptPlugin.getConfiguration()

  Assert.assertEquals("bar", coffeescriptPlugin.getConfiguration()

  Assert.assertEquals("baz", coffeescriptPlugin.getConfiguration()

Mockito's ArgumentCaptor

I guess this is really a testing tools article, rather than a Roo article.

The ArgumentCaptor API is really useful to see what the values were for a mock that was called by your class under test. This is a way to verify that we were passing in the right plugin configuration to our Roo projectManager, which, after all, we aren't testing. That's the Roo team's job!


Looking at it from a distance, Roo is just a Java platform that generates, manipulates and configures applications. So it can really do anything. However, rather than testing by re-deploying 10 times, we can run a fast Junit test 10 times instead.

If you go to my Silly Weasel link at the top of the blog page, you'll see the OBR URL for getting my Coffeescript, jQuery and (soon) Site add-ons. You can browse my maven repository (the same URL without the repository.xml ending) and grab the source for anything I've released.

Please send me comments if you'd like to add to this discussion.







Published at DZone with permission of Ken Rimple , DZone MVB .

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}