Achieving 100% code coverage. Testing getters and setters.

There’s been much debate about how much code should be tested. In particular, whether to test accessor methods (here, I’ll call accessor methods both getters and setters, i.e. methods to read or write an object’s property) has often been the subject of such debate.

While I myself think that testing effort should be devoted to more interesting things, others differ. Whether we agree or not, we might be working for a customer whose test coverage requirements are unsatisfiable without testing them. These requirements can be as high as 100%.

In such circumstances there’s an easy way to have your accessor methods tested, thanks to OpenPojo. Please, take a look at their wiki to have an idea of what this library is about.

Now let’s see a way to take advantage of it for our particular scenario.

First of all, we’ll need the following dependency if we’re using maven:

<dependency>
	<groupId>com.openpojo</groupId>
	<artifactId>openpojo</artifactId>
	<version>${openpojo.version}</version>
</dependency>

I’ll also include the Cobertura Maven plugin to check the test coverage later on:

<reporting>
	<plugins>
		<plugin>
			<groupId>net.sourceforge.cobertura</groupId>
			<artifactId>cobertura</artifactId>
			<version>${cobertura.version}</version>
		</plugin>
	</plugins>
</reporting>

Now, suppose we have a couple of data transfer objects like these:

public class Attachment {

	private String filename;
	private String base64Content;
	private String contentType;

	public String getFilename() {
		return filename;
	}

	public String getBase64Content() {
		return base64Content;
	}

	public String getContentType() {
		return contentType;
	}

	public void setFilename(final String filename) {
		this.filename = filename;
	}

	public void setBase64Content(final String contentBytes) {
		this.base64Content = contentBytes;
	}

	public void setContentType(final String contentType) {
		this.contentType = contentType;
	}
	[...]
public class MailMessage {

	private String from;
	private List<String> bcc;
	private List<String> cc;
	private String replyTo;
	private String subject;
	private String text;
	private List<String> to;
	private List<Attachment> attachments = new ArrayList<Attachment>();

	public String getFrom() {
		return from;
	}

	public List<String> getBcc() {
		return bcc;
	}

	public List<String> getCc() {
		return cc;
	}

	public String getReplyTo() {
		return replyTo;
	}

	public String getSubject() {
		return subject;
	}

	public String getText() {
		return text;
	}

	public List<String> getTo() {
		return to;
	}

	public void setFrom(final String from) {
		this.from = from;
	}

	public void setBcc(final List<String> bcc) {
		this.bcc = bcc;
	}

	public void setCc(final List<String> cc) {
		this.cc = cc;
	}

	public void setReplyTo(final String replyTo) {
		this.replyTo = replyTo;
	}

	public void setSubject(final String subject) {
		this.subject = subject;
	}

	public void setText(final String text) {
		this.text = text;
	}

	public void setTo(final List<String> to) {
		this.to = to;
	}

	public List<Attachment> getAttachments() {
		return attachments;

	}
	[...]

We’re going to write an OpenPojo accessor validator and call it from the JUnit test classes for both Data Transfer Objects.
In order to reuse code, we can write a single validator method in a utility class. This method will receive a single parameter: the class whose accessors will be tested.

public class PojoTestUtils {

	private static final Validator ACCESSOR_VALIDATOR = ValidatorBuilder.create()
													.with(new GetterTester())
													.with(new SetterTester())
													.build();

	public static void validateAccessors(final Class<?> clazz) {
		ACCESSOR_VALIDATOR.validate(PojoClassFactory.getPojoClass(clazz));
	}
}

Test classes can now use it:

public class AttachmentTest {

	@Test
	public void testAccesors_shouldAccessProperField() {

		PojoTestUtils.validateAccessors(Attachment.class);
	}
	[...]
public class MailMessageTest {

	@Test
	public void testAccesors_shouldAccessProperField() {

		PojoTestUtils.validateAccessors(MailMessage.class);
	}
	[...]

Time to check our test coverage:

mvn clean cobertura:cobertura

Finally, if you check the generated report you’ll see our longed-for 100% coverage in all its greenness.

Coverage Report

That’s all for today. Make sure you read OpenPojo’s documentation. There are more use cases you might be interested in.

Testing a cacheable method with Mockito

The Spring framework provides a simple way to cache the value returned by a method.
Basically, you annotate a method with @Cacheable and next time you call it with the same arguments, you get the cached value avoiding re-executing the method’s code.
In the example we’re going to use, the Spring cache infrastructure will be backed by Ehcache. These are the basic Maven dependencies we’ll need:

	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-context</artifactId>
		<version>3.1.2.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>net.sf.ehcache</groupId>
		<artifactId>ehcache-core</artifactId>
		<version>2.5.0</version>
		<scope>runtime</scope>
	</dependency>
	<dependency>
		<groupId>cglib</groupId>
		<artifactId>cglib</artifactId>
		<version>2.2.2</version>
		<scope>runtime</scope>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-test</artifactId>
		<version>3.1.2.RELEASE</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.11</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.mockito</groupId>
		<artifactId>mockito-all</artifactId>
		<version>1.9.5</version>
		<scope>test</scope>
	</dependency>

The method we’re going to cache is a service method that returns some (possibly expensive) database record count:

import org.springframework.cache.annotation.Cacheable;

public class CacheableService {

	private EntityDao entityDao;

	public int someEntityCount(final CriteriaDto criteria) {
		return entityDao.count(criteria);
	}
	[...]

The CriteriaDto class is as follows:

public class CriteriaDto {

	private String criterion1;
	private String criterion2;
	private String otherProperty;
	
	[...]

We want that method to return the cached value whenever it’s repeatedly invoked with the same criteria. To complicate matters further, let’s suppose that only the fields criterion1 and criterion2 affect the returned record count.
Those requirements can be met by preceding the method with the following annotation:

	@Cacheable(value = "entityCount", key = "{ #criteria.criterion1, #criteria.criterion2 }")
	public int someEntityCount(final CriteriaDto criteria) {
	[...]

As you can see, the relevant criteria for the cache can be specified via a SpEL expression in the key argument. The other argument, value is the name of the cache that will be used.

Assuming you’re using the venerable XML Spring configuration, you can set up the cache service with the following XML fragment in your application context:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:cache="http://www.springframework.org/schema/cache"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd   http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
	http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">

	 [...]
	 
	<cache:annotation-driven cache-manager="countCacheManager"/>

	<bean id="countCacheManager"
		  class="org.springframework.cache.ehcache.EhCacheCacheManager">
		  <property name="cacheManager" ref="ehcache"></property>
	</bean>

	<bean id="ehcache"
		  class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
		  <property name="configLocation" value="META-INF/count-ehcache.xml"></property>
	</bean>
	 [...]

Lastly, we need to provide the referenced Ehcache configuration file (count-ehcache.xml in this case):

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
	<cache 
	       name="entityCount"
	       maxElementsInMemory="10"
	       timeToLiveSeconds="300"
	       logging="true"
	       statistics="true"
	        />    
</ehcache>

The important configuration item here is the cache’s name attribute, which must match the value specified in the @Cacheable annotation.
Now it’s time to test the correct behaviour of our cached method.
The cache will work as expected if the actual method’s code is executed only the first time the method is called with equivalent criteria.
First of all, let’s prepare a test with two different but equivalent CriteriaDTO objects.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/META-INF/applicationContext.xml")
public class CacheableServiceTest {
	
	@Autowired
	private CacheableService serviceUnderTest;
	
	@Test
	public void testSomeEntityCountCalledTwice_shouldCallDaoMethodOnce() {
		
		// Local fixture set-up
		CriteriaDto criteria1 = new CriteriaDto();
		criteria1.setCriterion1("c1");
		criteria1.setCriterion2("c2");
		criteria1.setOtherProperty("c3a"); // Should be ignored by Cacheable annotation
		
		CriteriaDto criteria2 = new CriteriaDto();
		criteria2.setCriterion1("c1");
		criteria2.setCriterion2("c2");
		criteria2.setOtherProperty("c3b"); // Should be ignored by Cacheable annotation
	[...]

The class under test, CacheableService has a collaborating class: EntityDao. We’re going to substitute it with a mock.

	@Test
	public void testSomeEntityCountCalledTwice_shouldCallDaoMethodOnce() {
		
		// Local fixture set-up
		CriteriaDto criteria1 = new CriteriaDto();
		criteria1.setCriterion1("c1");
		criteria1.setCriterion2("c2");
		criteria1.setOtherProperty("c3a"); // Should be ignored by Cacheable annotation
		
		CriteriaDto criteria2 = new CriteriaDto();
		criteria2.setCriterion1("c1");
		criteria2.setCriterion2("c2");
		criteria2.setOtherProperty("c3b"); // Should be ignored by Cacheable annotation
		
		// Mock installation
		EntityDao mockEntityDao = Mockito.mock(EntityDao.class);
		serviceUnderTest.setEntityDao(mockEntityDao);
		[...]

Lastly, we’re going to call the method under test (someEntityCount) with both criteria objects. If everything works as expected, the second call will return the value cached in the first invocation, avoiding the call to the potentially expensive DAO method.
Since the DAO object used in the test is actually a mock object, we can use Mockito.verify to check its use. More specifically, we’ll use the optional VerificationMode parameter to make sure that the method has only been called once.
Here’s the full test method:

	@Test
	public void testSomeEntityCountCalledTwice_shouldCallDaoMethodOnce() {
		
		// Local fixture set-up
		CriteriaDto criteria1 = new CriteriaDto();
		criteria1.setCriterion1("c1");
		criteria1.setCriterion2("c2");
		criteria1.setOtherProperty("c3a"); // Should be ignored by Cacheable annotation
		
		CriteriaDto criteria2 = new CriteriaDto();
		criteria2.setCriterion1("c1");
		criteria2.setCriterion2("c2");
		criteria2.setOtherProperty("c3b"); // Should be ignored by Cacheable annotation
		
		// Mock installation
		EntityDao mockEntityDao = Mockito.mock(EntityDao.class);
		serviceUnderTest.setEntityDao(mockEntityDao);
		
		// First call with criteria1
		serviceUnderTest.someEntityCount(criteria1);
		
		// Second call with criteria2
		serviceUnderTest.someEntityCount(criteria2);
		
		// Verification
		Mockito.verify(mockEntityDao, Mockito.times(1)).count(Mockito.any(CriteriaDto.class));
	}

As you can see, we’ve used the method times to specify the number of times we expect the method to have been called during the test and any to tell Mockito that we don’t care about the actual parameters passed in the method invocations.

This is an easy way to test the behaviour of a cached method. It could be further refined in several ways: verifying the call with the right parameters, adding a method to test that the cached value is not returned when the criteria objects differ, etc.
I hope you find this article useful and, as usual, I’ll be glad to read your comments.