A Test-Driven Development Stack for Java: Maven, Jetty, Mockito, and JAX-RS, Page 2
Jetty Integration with the Maven Testing Lifecycle
I have become a huge fan of Jetty. Its fast startup and seamless integration with Maven give you a large productivity boost over traditional J2EE approaches (e.g., deploying the infamous EAR or WAR file). Embedded Jetty is capable of running directly off your code, without the need to create a WAR file. It also scans all of your Java classes automatically and restarts the context if any of them get changed (although that can sometimes cause PermGen errors, particularly with Spring and AOP classes). Nevertheless, it was far more productive than our previous J2EE/Ant/WebSphere stack.
From a TDD perspective, Maven perfectly integrates with Jetty by starting it up automatically before running integration tests and shutting it down as soon as the tests are finished. This makes running integration tests very smooth and easy.
Just add the Jetty plugin to your <build><plugins> section in pom.xml like this:
<plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>
plugin</artifactId> <version>6.1.20</version> <executions> <execution> <id>start-
pre-integration-test</phase> <goals> <goal>run</goal> </goals> <configuration> <daemon>true</daemon> </configuration> </execution> <execution> <id>stop-
jetty</id> <phase>post-integration-test</phase> <goals> <goal>stop</goal> </goals> </execution> </executions> </plugin>
From that point on, you can run your web application using embedded Jetty by calling "mvn jetty:run".
Using Mock Objects for Unit Tests
We started off by using the established EasyMock library, but I soon discovered Mockito, the new mock object on the block. I was very impressed with its easy syntax and ability to seamlessly mock both interfaces and concrete classes. In a Spring-based application, this allows you to replace the injected dependencies in a component with mock versions that return hard-coded test values. We were able to test our service by mocking out the Hibernate DAOs it depends onwithout actually running the app or being connected to any database. Here's an example:
PersonDao dao = mock(PersonDao.class); Person p1 = new Person(); p1.setId(1); p1.setFirstName("John"); p1.setLastName("Doe"); Person p2 = new Person(); p2.setId(2); p2.setFirstName("Jane"); p2.setLastName("Doe"); List<Person> all = new LinkedList<Person>(); all.add(p1); all.add(p2); //return mocked result set on find when(dao.findAll()).thenReturn(all); //call the main method we want to test List<Person> result = service.findAll(); //verify the method was called verify(dao).findAll(); //verify correct result returned assertEquals(2,result.size());
If you deal with a system that does not have easy entry points for integration testing, using mock objects may be your best solution.
To add Mockito to your project, just add this code in the <dependencies> section of your pom.xml:
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <version>1.8.0</version> </dependency>