You have probably heard the word Arquillian, a child of JBoss Community, "a revolutionary testing platform built on the JVM that substantially reduces the effort required to write and execute Java middleware integration and functional tests". I put my fingers on it about a year ago, but have abundond it. It was still young and somewhat clumsy; too may bugs; too many problems. But, it is back! with the new and flashy look! first brand new release! And back am I, curious, excited, willing to found out how much better it will make my life, a life of a technology adict.
At the moment the rumors of Arquillian release have reached my hears, I was busy developing a REST client for a REST resource that did not exist yet. The contracs were defined, the few lines of code were already writtern, unit tests were in place, but the feeling that things may wrong got stuck in my guts. You may guess the cure - it was Arquillian.
Let see what I had on my table. Well, it was SeatClient calling SeatResource to find out whether a seat is available by exchanging JSON messages. SeatClient was backed up by Spring MVC version 3.1.1 and its RestTemplate to make my life easy. It all looked very easy
POM as follows
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${version.spring.framework}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.7</version>
</dependency>
and Java code like this
@Component public class SeatClient
{
@Autowired private RestTemplate restTemplate;
@Value("${url}") private String url;
public String retrieveSeatStatus()
{
String result = null;
String resourceUrl = url + "/seat";
Seat seat = restTemplate.getForObject(resourceUrl, Seat.class);
result = seat.getStatus();
return result;
}
}
Unit test makes me happy, since it is simple and green. But, happy I am not. Because, I do not know whether injection of the resources works fine, neither I know whether domain object is correclty marshalled/unmarshalled into/from JSON message and whether resource is called at all.
The first think that comes into my mind is mock of a REST resource. But, I do not want it to be simply plain mock, I want it to be a real mock, the one that receives my real message, the one that umarshalls my real JSON message and sends me a real response. This is when Arquillian smiled.
To work then!
First I make a real REST resource using Spring MVC
@Controller
public class SeatResource
{
@RequestMapping(value="/seat",
method=RequestMethod.GET,
produces = "application/json")
@ResponseBody
public Seat retrieveSeat()
{
Seat result = new Seat();
result.setStatus("OK");
return result;
}
}
Then I add released Arquillian dependencies in POM
<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-container-spi</artifactId>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-container</artifactId>
<version>1.0.0.Final</version>
<scope>test</scope>
</dependency>
Now, when I have a real resource I need a real server to run it in. The reference to the Arquillian documentation reveals the following list. It makes me more then satisfied, even impressed. It lets me choose between a number of known servers, letting me to deploy my real resource on either embedded, managed or remote instance. I modestly pick up embedded Tomcat from this festive table. It is more then enough.
<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-tomcat-embedded-6</artifactId>
<version>1.0.0.CR3</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>catalina</artifactId>
<version>${version.org.apache.tomcat}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>coyote</artifactId>
<version>${version.org.apache.tomcat}</version>
<scope>provided</scope>
</dependency>
Now comes the time to write a test, a real one. This test is more then simple one. Not only will it test the client, it will also inject it into the test with the following Spring application context configuration file
<beans xmlns="...>
<context:annotation-config />
<context:component-scan base-package="org.devtoolbox.seat"/>
<context:property-placeholder location="classpath:app.properties"/>
<bean name="restTemplate" class="org.springframework.web.client.RestTemplate"/>
</beans>
Then, with my help, it will create WAR file using ShrinkWrap API and deploy it on embedded Tomcat server.
@Deployment(testable = false)
@OverProtocol("Servlet 2.5")
public static WebArchive create()
{
return ShrinkWrap
.create(WebArchive.class, "spring-rest-test.war")
.addClasses(Seat.class, SeatResource.class)
.addAsLibraries(
resolveArtifact(
"org.springframework:spring-webmvc",
"org.codehaus.jackson:jackson-mapper-asl"))
.addAsWebInfResource(
"org/devtoolbox/seat/resource/seatResource-web.xml",
"web.xml")
.addAsWebInfResource(
"org/devtoolbox/seat/resource/seatResource-servlet.xml",
"rest-train-servlet.xml")
.addAsWebInfResource(
"org/devtoolbox/seat/resource/seatResource-applicationContext.xml",
"applicationContext.xml");
}
public static File[] resolveArtifact(String... artifacts)
{
MavenDependencyResolver mvnResolver =
DependencyResolvers.use(MavenDependencyResolver.class);
mvnResolver.loadMetadataFromPom("pom.xml");
return mvnResolver.artifacts(artifacts).resolveAsFiles();
}
Any selfrespecting WAR needs real web.xml, so I obedient create one
<web-app ...>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>rest-train</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest-train</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
The job is done! I click the button and overwell with satisfaction. I hope you to.
svn co https://devtoolbox.googlecode.com/svn/trunk/arquillian-rest-spring-test
Download Arquillian-rest-spring-test
Recent Comments