EasyMock in 5 minutes

January 1st, 2009  | Tags: , ,

A couple of months ago I started in a new project at IBM. That new project is a big challenge in my life, certainly it is the biggest project I have already worked.
As any new project, there are new tools, APIs, frameworks, that we need to learn. In that project for example, I had to learn the newest EasyMock. Actually, I’ve already used EasyMock a long time ago (maybe in 2005), but in the last years, I was using JMock instead.
Fortunately, the EasyMock 2.4 is similar than JMock, and because of this I had no trouble to learn it.
In this short topic, I’m going to show up how to get started with EasyMock 2.4. This topic doesn’t intend to be a tutorial, only an example of how the EasyMock is simple and can help us in the mockering.
Before get started, make sure that you hava Java 1.5 or higher installed and JUnit 4 (JUnit 3 is also supported, but I really like the annotations features :) ).

Downloading EasyMock

Basically you have to choices: Use a build tool (like Maven) to manage the JARs dependencies or to to the EasyMock’s official website: http://www.easymock.org/ and download its latest version (2.4). Probably you’re gonna download a file called easymock2.4.zip. Extract that file and a easymock2.4 folder will be created. There are documentation, javadoc and samples within the directory, but you will use only the easymock.jar file.

Creating the project

I’m going to use Maven and M2Eclipse plugin to create that project into Eclipse, but you’re free to use another IDE. You can check a Maven example here.
Besides create the project,also add the junit-4.5.jar and easymock.jar file into classpath. If you’re using Maven, add the junit-4.5 and easymock dependencies. The pom looks like below:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>EasyMockExample</groupId>
  <artifactId>EasyMockExample</artifactId>
  <packaging>jar</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>EasyMockExample</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.5</version>
      <scope>test</scope>
    </dependency>
    <dependency>
    	<groupId>org.easymock</groupId>
    	<artifactId>easymock</artifactId>
    	<version>2.4</version>
    </dependency>
  </dependencies>
</project>

Creating the Interfaces and Classes

Let’s use a common example that happens in the projects that use EJB2 and remote call. We have a service layer, that will look up for some values from Repository (DAO). That Repository will return the Entity and the Service must copy only the required values to the TO (Transfer Object).
We’re going to test the Service layer, hence, we must MOCK the Repository.
Note: Use the approach (BO and VO) only if you are using EJB2 (CMP entities) with remote call. This post is merely an example.
All the interfaces and classes could look like below:

Customer Entity

package com.jairrillo.easymockexample.entities;
public class Customer {
	private Integer id;
	private String name;
	private String phoneNumber;
	//Getters and Setters

Note: Supposing that is a CMP entity (not serializable). Hence, we cannot send it through the remote call (it must be serializable to do that)
CustomerTO : Transfer Object

package com.jairrillo.easymockexample.transferobjects;
import java.io.Serializable;
public class CustomerTO implements Serializable {
	private static final long serialVersionUID = 1L;
	private String name;
	public CustomerTO() {	
	}
	public CustomerTO(String name) {
		this.name = name;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

Note: That is a Serializable Object. We only copy the required values. In that case, only the Customer’s name is required.
CustomerRepository (DAO)

package com.jairrillo.easymockexample.repositories;
import java.util.List;
import com.jairrillo.easymockexample.entities.Customer;
public interface CustomerRepository {	
	public List<Customer> getListOfPendingCustomers();
}

CustomerService (Business Object layer)

package com.jairrillo.easymockexample.services;
import java.util.List;
import com.jairrillo.easymockexample.repositories.CustomerRepository;
import com.jairrillo.easymockexample.transferobjects.CustomerTO;
public interface CustomerService {
	public List<CustomerTO> getListOfPendingCustomers();
	public void setRepository(CustomerRepository repository);
}

As you can see above, we have two interfaces (CustomerRepository and CustomerService) and two concrete classes (Customer and CustomerVO). Also, we need a new concrete class to implement the CustomerService. The class looks like (no implementation yet).

package com.jairrillo.easymockexample.services;
 
import java.util.List;
 
import com.jairrillo.easymockexample.repositories.CustomerRepository;
import com.jairrillo.easymockexample.transferobjects.CustomerTO;
 
public class CustomerServiceImpl implements CustomerService {
 
	private CustomerRepository repository;
 
	public List<CustomerTO> getListOfPendingCustomers() {
		// TODO Auto-generated method stub
		return null;
	}
 
	/**
	 * Inject the Repository through that method.
	 * We can use Spring, EJB or even Google Guice to do that.
	 * 
	 * @param repository
	 */
	public void setRepository(CustomerRepository repository) {
		this.repository = repository;
	}
}

Creating the Test Case

We’re going to test the CustomerServiceImpl class and mock the CustomerRepository interface.
If you’re using Maven, you can create the test case into src/test/java directory. If not, create a test directory in the same level than src. Below, following our test case.

package com.jairrillo.easymockexample.services;
 
 
import static org.easymock.EasyMock.*;
 
import java.util.ArrayList;
import java.util.List;
 
import static junit.framework.Assert.*;
 
import org.junit.Before;
import org.junit.Test;
 
import com.jairrillo.easymockexample.entities.Customer;
import com.jairrillo.easymockexample.repositories.CustomerRepository;
import com.jairrillo.easymockexample.transferobjects.CustomerTO;
 
public class CustomerServiceImplTest {
	/**
	 * Class underTest
	 */
	private CustomerService customerService;
	/**
	 * Mock object
	 */
	private CustomerRepository mock;
 
	@Before
	public void setUp() throws Exception {
		//Starting the class underTest
		this.customerService = new CustomerServiceImpl();
		//Starting mock object
		this.mock = createStrictMock(CustomerRepository.class);
	}
	/**
	 * This method test the getListOfPendingCustomers when none value is returned from
	 * Repository
	 * In that case, the method must return an Empty {@link java.util.List}
	 */
	@Test
	public void testGetListOfPendingCustomersWhenNoneCustomerIsRetrieved() {
		//Adding behavior for that method
		expect(this.mock.getListOfPendingCustomers()).andReturn(new ArrayList<Customer>());
		replay(this.mock);
		//Injecting Repository into CustomerService
		this.customerService.setRepository(this.mock);
		//Testing the return
		assertEquals(true, this.customerService.getListOfPendingCustomers().isEmpty());
	}
 
	/**
	 * This method test the getListOfPendingCustomers when only ONE value is returned from the Repository
	 */
	@Test
	public void testGetListOfPendingCustomersWhenOneCustomerIsRetrieved() {
		List<Customer> listCustomers = new ArrayList<Customer>();
		Customer customer = new Customer();
		customer.setId(1);
		customer.setName("Jair Rillo Junior");
		customer.setPhoneNumber("123456789");
		listCustomers.add(customer);
		//Adding behavior for that method
		expect(this.mock.getListOfPendingCustomers()).andReturn(listCustomers);
		replay(this.mock);
		//Injecting Repository into CustomerService
		this.customerService.setRepository(this.mock);
		//Testing the return
		List<CustomerTO> listCustomersTO = this.customerService.getListOfPendingCustomers();
		assertEquals(false, listCustomersTO.isEmpty());
		assertEquals(1, listCustomersTO.size());
		//Testing the returned value
		CustomerTO customerTO = listCustomersTO.get(0);
		assertEquals("Jair Rillo Junior", customerTO.getName());
	}	
}

As you can see above, EasyMock is really simple to use. Like other mock object, we must start it, add the behavior and test it.

Running the Test Case

Right click on Test Case class, go to Run As -> JUnit. You’re gonna get a RED BAR. It means the test failed, but why? Because our implementation class isn’t implement yet (duh). Let’s do that now.

Implementing The CustomerServiceImpl

The CustomerServiceImpl implemented looks like below:

package com.jairrillo.easymockexample.services;
 
import java.util.ArrayList;
import java.util.List;
 
import com.jairrillo.easymockexample.entities.Customer;
import com.jairrillo.easymockexample.repositories.CustomerRepository;
import com.jairrillo.easymockexample.transferobjects.CustomerTO;
 
public class CustomerServiceImpl implements CustomerService {
 
	private CustomerRepository repository;
 
	public List<CustomerTO> getListOfPendingCustomers() {
		//List that will be returned
		List<CustomerTO> listCustomerTO = new ArrayList<CustomerTO>();
		//Retrieving values from Repository
		List<Customer> listCustomers = repository.getListOfPendingCustomers();
		//Copying (only required) values to TO
		for (Customer customer : listCustomers) {
			//Only NAME is required for that requirement
			CustomerTO customerTO = new CustomerTO(customer.getName());
			//adding the CustomerTO to list
			listCustomerTO.add(customerTO);
		}
		return listCustomerTO;
	}
 
	/**
	 * Inject the Repository through that method.
	 * We can use Spring, EJB or even Google Guice to do that.
	 * 
	 * @param repository
	 */
	public void setRepository(CustomerRepository repository) {
		this.repository = repository;
	}
}

Supposing our entity has many attributes, as well as many objects related, however we want only send up the NAME (In a remote call, you can use a TO to transfer objects over the network when the entity is not serializable).

Running the Test Case again

Run again the test case and in this time you should get the GREEN BAR!!

Conclusion

With this topic, you can have an idea of how the EasyMock works. Of course it has others features, but it can be a starting point. In a real software, you should create more than only two test method, but I leave this homework for you.
I hope this topic be useful for anyone. If you have any question or comment, fell free to leave a message below.
You can download the example below here.

  1. capcase
    December 11th, 2009 at 01:45
    #1

    great tutorial

TOP