-
Notifications
You must be signed in to change notification settings - Fork 5
Tutorial (Java instrumentation)
If you are or have ever developed a J2EE 6 based application, you might have noticed that CDI is a foundational aspect of such architecture. It is supported by several J2EE application servers such as Caucho's Resin, IBM's WebSphere, Oracle's Glassfish, Red Hat's JBoss and many others. CDI is similar to core Spring and Guice frameworks. CDI simplifies and sanitizes the API for DI and AOP. If you have worked with Spring or Guice, you will find CDI easy to use and easy to learn.
CDI can be used standalone and can be embedded into any application. But how do we go around testing such applications? For that we can make use of Jglue CDI-Unit project.
This COLA Tests tutorial creates an imaginary Gherkin feature for the Starship example provided in Jglue's CDI-Unit user-guide.
The sample project is available on GitHub
File: pom.xml
...
<properties>
<cola.version>0.4.0</cola.version>
<cola.agent>${settings.localRepository}/com/github/bmsantos/cola-tests/${cola.version}/cola-tests-${cola.version}.jar</cola.agent>
</properties>
...
<dependency>
<groupId>com.github.bmsantos</groupId>
<artifactId>cola-tests</artifactId>
<version>${cola.version}</version>
<scope>test</scope>
</dependency>
...
</dependencies>
<build>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<argLine>-javaagent:${cola.agent}</argLine>
</configuration>
</plugin>
...
Features are business goals normally defined by the customer. Gherkin based frameworks are mainly used to validate the predefined business features and customer reported bugs. In other words, even though these frameworks can be used to validate the normal unit test, its main use is to test and ensure that customer requirements are satisfied.
With this in mind, the first step is then to find out the business features of the application.
Feature: Warp Travel
As a Starship commander
I want to switch to warp mode
So that I do not have to call bridge
Scenario: Should start engine
Given a stabilized Starship
When the Warp Engine is initiated
Then the Starship will warp
Because we are doing BDD/TDD, the tests will be created before the application itself. So, lets start by defining the test class and methods.
File: StarshipTest.java
public class StarshipTest {
@Feature
private final String warpTravel =
"Feature: Warp Travel\n"
+ "As a Starship commander\n"
+ "I want to switch to warp mode\n"
+ "So that I do not have to call bridge\n"
+ "\n"
+ "Scenario: Should start engine\n"
+ "Given a stabilized Starship\n"
+ "When the Warp Engine is initiated\n"
+ "Then the Starship will warp";
@Given("a stabilized Starship")
public void givenAStarship() {
}
@When("the Warp Engine is initiated")
public void initiateWarpEngine() {
}
@Then("the Starship will warp")
public void verifyStarshipIsWarping() {
}
}
The first thing you'll notice is the @Feature annotation used to specify the feature created in step 1. This information will be used to execute the scenarios steps in their respective order.
Side note: Notice that you can specify the feature in its own file by making use of the @Features annotation.
Next, you'll notice the different steps annotations used to exercise the feature scenarios. In this case, these are the Given, @When and @Then annotations.
With everything in place, you should now be able to run the test by executing the following maven command:
mvn test
With COLA Tests running, it is now time to implement the actual test. For that we will make use of Jglue CDI-Unit JUnit Runner:
@RunWith(CdiRunner.class)
public class StarshipTest {
@Feature
private final String warpTravel =
"Feature: Warp Travel\n"
+ "As a Starship commander\n"
+ "I want to switch to warp mode\n"
+ "So that I do not have to call bridge\n"
+ "\n"
+ "Scenario: Should start engine\n"
+ "Given a stabilized Starship\n"
+ "When the Warp Engine is initiated\n"
+ "Then the Starship will warp";
@Inject
private Starship starship;
@Given("a stabilized Starship")
public void givenAStarship() {
assertThat(starship.isRunning()).isFalse();
}
@When("the Warp Engine is initiated")
public void initiateWarpEngine() {
starship.start();
}
@Then("the Starship will warp")
public void verifyStarshipIsWarping() {
assertThat(starship.isRunning()).isTrue();
}
}
With the test ready, it is now time to create the missing classes to be tested:
public interface Engine {
void start();
boolean isRunning();
}
public class WarpDrive implements Engine {
private boolean isRunning = false;
public void start() {
isRunning = true;
}
public boolean isRunning() {
return isRunning;
}
}
public class Starship {
@Inject
private WarpDrive engine;
public void start() {
engine.start();
}
public boolean isRunning() {
return engine.isRunning();
}
}
And execute the tests once again to see them pass.
Licensed under the Apache License, Version 2.0 (the "License").