JBoss Community Archive (Read Only)

Arquillian Old

Writing your first Arquillian test

You're now going to write your first Arquillian test. But in order to write a test, we need to have something to test. So let's first create a managed bean that we can invoke.

We'll help out those Americans still trying to convert to the metric system by providing them a Fahrenheit to Celsius converter.

Here's our TemperatureConverter:

public class TemperatureConverter {

   public double convertToCelsius(double f) {
      return ((f - 32) * 5 / 9);
   }

   public double convertToFarenheit(double c) {
      return ((c * 9 / 5) + 32);
   }

}

Now we need to validate that this code runs. We'll be creating a test in the src/test/java classpath of the project.

Granted, in this trivial case, we could simply instantiate the implementation class in a unit test to test the calculations. However, let's assume that this bean is more complex, needing to access enterprise services. We want to test it as a full-blown container-managed bean, not just as a simple class instance. Therefore, we'll inject the bean into the test class using the @Inject annotation.

You're probably very familiar with writing tests using either JUnit or TestNG. A regular JUnit or TestNG test class requires two enhancements to make it an Arquillian integration test:

The deployment archive for the test is defined using a static method annotated with Arquillian's @Deployment annotation that has the following signature:

public static Archive<?> methodName();

We'll add the managed bean to the archive so that we have something to test. We'll also add an empty beans.xml file, so that the deployment is CDI-enabled:

@Deployment
public static JavaArchive createTestArchive() {
   return ShrinkWrap.create(JavaArchive.class, "test.jar")
      .addClasses(TemperatureConverter.class)
      .addAsManifestResource(
            new ByteArrayAsset("<beans/>".getBytes()), 
            ArchivePaths.create("beans.xml"));
}

The JUnit and TestNG versions of our test class will be nearly identical. They will only differ in how they hook into the Arquillian test runner.

When creating the JUnit version of the Arquillian test case, you will define at least one test method annotated with the JUnit @Test annotation and also annotate the class with the @RunWith annotation to indicate that Arquillian should be used as the test runner for this class.

Here's the JUnit version of our test class:

@RunWith(Arquillian.class)
public class TemperatureConverterTest {
   @Inject
   private TemperatureConverter converter;

   @Deployment
   public static JavaArchive createTestArchive() {
      return ShrinkWrap.create(JavaArchive.class, "test.jar")
         .addClasses(TemperatureConverter.class)
         .addAsManifestResource(
            EmptyAsset.INSTANCE, 
            ArchivePaths.create("beans.xml")); 
   }

   @Test
   public void testConvertToCelsius() {
      Assert.assertEquals(converter.convertToCelsius(32d), 0d);
      Assert.assertEquals(converter.convertToCelsius(212d), 100d);
   }

   @Test
   public void testConvertToFarenheit() {
      Assert.assertEquals(converter.convertToFarenheit(0d), 32d);
      Assert.assertEquals(converter.convertToFarenheit(100d), 212d);
   }
}

TestNG doesn't provide anything like JUnit's @RunWith annotation, so instead the TestNG version of the Arquillian test case must extend the Arquillian class and define at least one method annotated with TestNG's @Test annotation.

public class TemperatureConverterTest extends Arquillian {

   @Inject
   private TemperatureConverter converter;

   @Deployment
   public static JavaArchive createTestArchive() {
      return ShrinkWrap.create(JavaArchive.class, "test.jar")
         .addClasses(TemperatureConverter.class)
         .addAsManifestResource(
            EmptyAsset.INSTANCE,, 
            ArchivePaths.create("beans.xml")); 
   }

   @Test
   public void testConvertToCelsius() {
      Assert.assertEquals(converter.convertToCelsius(32d), 0d);
      Assert.assertEquals(converter.convertToCelsius(212d), 100d);
   }

   @Test
   public void testConvertToFarenheit() {
      Assert.assertEquals(converter.convertToFarenheit(0d), 32d);
      Assert.assertEquals(converter.convertToFarenheit(100d), 212d);
   }
}

As you can see, we are not instantiating the bean implementation class directly, but rather using the CDI reference provided by the container at the injection point, just as it would be used in the application. (If the target container supports EJB, you could replace the @Inject annotation with @EJB). Now let's see if this baby passes!

JBoss.org Content Archive (Read Only), exported from JBoss Community Documentation Editor at 2020-03-10 12:18:47 UTC, last content change 2011-04-16 11:44:56 UTC.