December 20, 2014
Hot Topics:

Mockito: Java Unit Testing with Mock Objects

  • May 14, 2010
  • By Jacek Furmankiewicz
  • Send Email »
  • More Articles »

One of the hallmarks of an experienced developer is an appreciation of the importance of unit and integration testing. Although integration testing is the ultimate way to verify application functionality, it does come with a lot of startup/execution/shutdown overhead. Sometimes it is easier to verify particular application components in isolation, without the actual application running.

In this article, I show how you can still thoroughly test components that would usually require integration testing using regular, basic JUnit tests. Using code samples, I will walk you through writing unit tests for a JAX-RS REST Web service that fetches Person data from a database and returns it to the caller. I will demonstrate how to write a JUnit unit test for such service -- without having to actually deploy it into a running Web container. You will mock out the Hibernate DAO to simulate interaction with a database.

Unit Tests, Mock Objects and Mockito

Any "live" business logic component relies on interactions with other components. It may be a POJO with some additional business logic, a Hibernate/JPA DAO returning some entities from the database, or an HTTP call (via REST or SOAP) to an external system.

Mock objects allow us to mock out these dependencies. Using standard dependency injection (regardless of whether you are using Java EE, Spring or Guice), you can then inject those mocked objects into your business logic component and verify its interactions. Mock objects are one of the biggest payoffs that come with adopting dependency injection as the core of your application's architecture.

Java is perfectly suited for providing this functionality, thanks to its capabilities for runtime bytecode manipulation and object proxy generation. In fact, quite a few mock object libraries are available in the Java ecosystem (EasyMock, for example), but my preference has been to use Mockito. It has an incredibly easy and logical API and is under very active development.

You can download it manually from the Mockito website, or if you use Maven/Ivy/Grape, just add it as a test-scoped dependency. (At the time of writing, the latest version was 1.8.4.)

JAX-RS Service Code Sample

You will be testing the following simple JAX-RS REST service, deployed as a Spring bean. Note that the attached code samples are a regular Maven project. Just execute mvn test or mvn integration-test to run unit tests and integration tests, respectively. You should be able to open it in any modern Java IDE.

@Service("personService")
@Path(PersonService.PATH)
public class PersonService {
 
 public static final String PATH = "/person";

 private PersonDao dao;
 @Autowired public void setPersonDao(PersonDao dao) {
 this.dao = dao;
 }
 
 @GET
 public List findAll() {
 List people = dao.findAll();
 return (people.size() > 0) ? people : null;
 }
 
 @GET @Path("{id}")
 public Response find(@PathParam("id") Integer id) {
 Person p = dao.findByPrimaryKey(id);
 if (p != null) {
 return Response.ok(p).build();
 } else {
 return Response.status(Status.NOT_FOUND).build();
 }
 }

 @POST 
 public Response add(@FormParam("firstName") String firstName,
 @FormParam("lastName") String lastName, 
 @FormParam("email") String email) {
 
 try {
 
 Person person = new Person();
 person.setFirstName(firstName);
 person.setLastName(lastName);
 person.setEmail(email);
 Integer id = dao.save(person);
 
 return Response.created(UriBuilder.fromPath(PATH + 
"/{0}").build(id)).entity(person).build(); } catch (Exception ex) { return Response.serverError().build(); } } @PUT @Path("/{id}") public Response update(@PathParam("id") Integer id, @FormParam("firstName") String firstName, @FormParam("lastName") String lastName, @FormParam("email") String email) { try { Person person = dao.findByPrimaryKey(id); if (person != null) { if (firstName != null) { person.setFirstName(firstName); } if (lastName != null){ person.setLastName(lastName); } if (email != null) { person.setEmail(email); } dao.update(person); return Response.ok(person).build(); } else { return Response.noContent().build(); } } catch (Exception e) { return Response.serverError().build(); } } @DELETE public Response deleteAll() { try { dao.deleteAll(); return Response.ok().build(); } catch (Exception e) { return Response.serverError().build(); } } @DELETE @Path("/{id}") public Response delete(@PathParam("id") Integer id) { try { dao.deleteByPrimaryKey(id); return Response.ok().build(); } catch (Exception e) { return Response.serverError().build(); } } }


Testing a Web service implies that you have to deploy it. But with mock objects, that assumption is incorrect.


Tags: Java, Unit Testing, Mock Objects



Page 1 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel