Mocking a constructor. A unit test for a factory method.

Introduction

In our previous post we have learnt the basics of using Mockito to write true unit tests.
Now we are going to unit test a factory method. The particular implementation used here is the one described in the traditional Data Access Object pattern for the DAO Factory.
In the process we’re going to stumble upon some Mockito’s limitations and we’ll see a way to overcome them.

The factory method

Let’s suppose we have a typical DAOFactory class exposing a factory method with the following signature:

public static DAOFactory getDAOFactory(Type type)

The method is meant to be called by clients in order to get a DAO Factory implementation for a particular database vendor. For instance, by calling DAOFactory.getDAOFactory(DAOFactory.Type.MARIADB) we’d get an instance of the class MariaDbDAOFactory, suited to work with a MariaDB database.

The test

Then let’s write a unit test for that scenario: obtaining a MariaDbDAOFactory object by calling the factory method with the type MARIADB.
First of all, we can establish the following success condition for the test: it will pass if and only if the method creates and return a MariaDbDAOFactory instance when it’s called with a MARIADB type as the parameter.
By following the naming conventions advised in xUnit Test Patterns, we can start writing our method like this:

@Test
public void testGetDAOFactoryMariaDb_shouldCreateAndReturnMariaDbDAOFactory() throws Exception {

	// XUnit Phase 1: Setup

	// XUnit Phase 2: Exercise

	// XUnit Phase 3: Verification

}

I have also written some comments as placeholders to better organise the testing code according to the XUnit phases (teardown phase is not necessary here).
Since we want a true unit test, we should mock the collaborating classes, like MariaDbDAOFactory.
When writing tests, most of the time we’ll be dealing with regular method calls on an instance of a collaborating class. But this case is different, since the interaction consists of invoking a constructor of the class to be mocked.
This is where the difficulty lies, since Mockito cannot mock constructors. We must adopt, therefore, a different approach.

Enter PowerMock

The framework PowerMock extends other mocking libraries with advanced features, like mocking constructors, static methods, final methods, etc.
One of the extended libraries happens to be Mockito. This allows us to utilise PowerMock while leveraging our experience with Mockito.
Now that we have the tool we need to mock constructors, let’s see how to use it.
Before going further, if you use Maven, these are the dependencies you’re going to need:

  	<dependency>
  		<groupId>org.powermock</groupId>
  		<artifactId>powermock-api-mockito</artifactId>
  		<version>1.5</version>
  		<scope>test</scope>
  	</dependency>
  	<dependency>
  		<groupId>org.powermock</groupId>
  		<artifactId>powermock-module-junit4</artifactId>
  		<version>1.5</version>
  		<scope>test</scope>
  	</dependency>

Now, let’s prepare the test class. PowerMock tests run with their own JUnit runner: PowerMockRunner.
Also, since PowerMock’s extended features requires byte-code manipulation, it’s also necessary to specify which classes will be prepared in that way. The annotation @PrepareForTest allows us to do it.
Now, our test class looks like this:

@RunWith(PowerMockRunner.class)
@PrepareForTest(DAOFactory.class)
public class DAOFactoryTest {
[...]

Note that the class to be prepared is the class invoking the constructor, and not the class to be instantiated.
Next, we need to record the mock behaviour, which we’ll do in two steps:

  1. Creating the mocked new instance of MariaDbDAOFactory. For this purpose we’ll use PowerMockito.mock instead of Mockito.mock
  2. Specifying how the constructor invocation is going to behave. Basically, we are going to tell PowerMock to return our recently created mocked instance whenever the constructor is called.

This is the actual code:

		// XUnit Phase 1: Setup
		MariaDbDAOFactory mockedDAOFactory = PowerMockito.mock(MariaDbDAOFactory.class);

		PowerMockito.whenNew(MariaDbDAOFactory.class)
					.withNoArguments()
					.thenReturn(mockedDAOFactory);

Now we can exercise the method under test (DAOFactory.getDAOFactory):

		// XUnit Phase 2: Exercise
		DAOFactory daoFactory = DAOFactory.getDAOFactory(DAOFactory.Type.MARIADB);

Lastly, we need to verify that the tested method has actually called the MariaDbDAOFactory constructor. We’ll use PowerMockito.verifyNew for that.
Additionally, we can verify that the object returned by the tested method is indeed the mocked DAO factory we created in the setup phase. A simple JUnit assertEquals will suffice.
The complete test class will look like this:

@RunWith(PowerMockRunner.class)
@PrepareForTest(DAOFactory.class)
public class DAOFactoryTest {

	@Test
	public void testGetDAOFactoryMariaDb_shouldCreateAndReturnMariaDbDAOFactory() throws Exception {

		// XUnit Phase 1: Setup
		MariaDbDAOFactory mockedDAOFactory = PowerMockito.mock(MariaDbDAOFactory.class);

		PowerMockito.whenNew(MariaDbDAOFactory.class)
					.withNoArguments()
					.thenReturn(mockedDAOFactory);

		// XUnit Phase 2: Exercise
		DAOFactory daoFactory = DAOFactory.getDAOFactory(DAOFactory.Type.MARIADB);

		// XUnit Phase 3: Verification
		PowerMockito.verifyNew(MariaDbDAOFactory.class).withNoArguments();
		Assert.assertEquals(mockedDAOFactory, daoFactory);
	}
}

Final remarks

In this article we’ve learnt how to mock a constructor with the framework PowerMock using a real-life but admittedly simple example. The reasons behind this choice are purely educational. In your day-to-day work you may judge a factory method too simple and well-established to be worth testing. Or you may prefer some integration testing (instead of unit testing) for this method, avoiding any mocking at all.
Secondly, I’ve been using the term mock object instead of test double, which, although widely used, would be consider incorrect by purists. I recommend checking this site or its associated book for more accurate definitions.
Lastly, don’t hesitate in using the comments section to share your thoughts with the rest of us.

Unit Testing with Mock Objects

Unit Testing

A Java application consists (roughly) of several classes interacting.
The first step towards a reliable application is, therefore, to have well tested individual classes. This is precisely the purpose of unit testing: testing units of code in isolation from other units. In our case, we’ll consider the Java class as the unit of code.
The main advantage of testing the class in isolation is making sure that the potential errors we can stumble upon are due to defects in the class under test and not caused by defects on collaborating classes.

Achieving the isolation

However, classes work in cooperation with other classes, so, how can we isolate the tested class?
Well, the idea is substituting the collaborating classes with compatible classes whose implementation is so trivial that we can be confident on their correctness.
The instances of those classes are known as test doubles and, very often, they’re also called mock objects even if this is a little bit of a misnomer.

What should we substitute

Substituting every single collaborating object with a test double would certainly be overkilling. I guess no one would even think of replacing a String object with a mock object.
Choosing the candidates to be replaced is a matter of common sense. Most people would not use test doubles in the following cases:

  • Classes with deterministic behaviour from trusted third parties. The aforementioned String object would certainly fall into this category.
  • Classes with a trivial implementation. Think of data transfer objects that are mere bunches of properties.

Easing the pain of writing test doubles

Once we have identified the candidates to be replaced, it’s time to write the test doubles. But wait!, thanks to several available mocking frameworks, we can avoid most of the work.
Among those frameworks, my favourite is Mockito, which I find very flexible and feature-rich.
Let’s see what Mockito can do for us in this first phase.
First of all, it can create a mock object from an existing type like this:

CustomerDao customerDaoDouble = Mockito.mock(CustomerDao.class);

After this line, methods from customerDaoDouble either do nothing (void methods) or just return a trivial value (null, false, 0, etc.).
Sometimes this is enough but usually we’ll need a specific behaviour for our test to work. This is another situation in which Mockito can help us. We can easily specify the behaviour of our test doubles’ methods like this:

Mockito.when(customerDaoDouble.findOne(nonexistentCustomerId)).thenReturn(null);
[...]
Mockito.when(customerDaoDouble.findOne(existingCustomerId)).thenReturn(existingCustomer);

Now, whenever we invoke findOne with the parameter nonexistentCustomerId we will get null, and whenever we call findOne with the parameter existingCustomerId we will get the object existingCustomer.
The action of specifying the test doubles’ behaviour is commonly known as setting the expectations.

Replacing the real object

Now we have our test double ready. We just need to use it in place of the real object. Let’s see how.
First of all, our class under test can cooperate with other classes in several ways:

  • An object of the collaborating class is used as a parameter in a method of our class.
    In this case we can just pass the test double as a parameter:

    	stackUnderTest.push(mockedItem);
    	
  • An object of the collaborating class is used as a field in our class.
    Then we’ll have to install our test double using some method, usually with a setter or a constructor. Or even assign it directly if the field is not private.
    But what, might you ask, if there is no accessible method to set the field? Well, in this case I’d suggest to just write a setter method or a constructor to set it.
    If you’re concerned about the field being publicly writeable by any class, you can always make the method protected and place the test class in the same package under the test tree.
    Lastly, some may argue about the suitability of writing a method just to be used by test classes, but remember that designing for testability is widely seen as a good development practice.

    	[...]
    	CustomerDao customerDaoDouble = Mockito.mock(CustomerDao.class);
    	// Installing the test double in place of the real customer DAO
    	customerServiceUnderTest.setCustomerDao(customerDaoDouble);
    	// Exercise some customerServiceUnderTest's method
    	[...]
    	
  • An object of the collaborating class is created inside a method.
    This kind of objects cannot be replaced by test doubles. If we need to do it, some refactoring will be necessary: promote the local object to field and provide a setter method for it.

Verification

The purpose of tests is to verify the correctness of our software. There are two ways we can do that:

  1. State verification. Since the execution of our software under test changes the state of the system, a straightforward verification strategy lies on checking the state of the modified objects. A typical example of this strategy is the verification through assertions of the object returned by a method.
    	Assert.assertEquals(expectedObject, stackUnderTest.pop());
    	
  2. Behaviour verification. A different approach to verification consists in ensuring that our tested class interacts with its collaborating classes in the expected way.
    This approach is of particular interest in this article, since it’s another area where Mockito can help us. In particular, the provided method verify makes this kind of verification pretty easy.
    In its simplest use, this method is used like this:

    	Mockito.verify(testDouble).expectedMethod(expectedParameters);
    	

    A JUnit test with such a verification will pass only if the method expectedMethod is invoked with the parameters expectedParameters.
    Let’s illustrate this with an example. Suppose we want to test a service class which uses a DAO in order to create a new customer.
    If we want our test to be a real unit test, we should isolate our service class by “mocking” the DAO object.
    In this scenario, our only possible verification strategy seems to be checking that the DAO’s creation method is invoked with the right parameters. Let’s see how:

    	[...]
    	// Creating the test double
    	CustomerDao customerDaoDouble = Mockito.mock(CustomerDao.class);
    	
    	// Installing the test double in place of the real customer DAO
    	customerServiceUnderTest.setCustomerDao(customerDaoDouble);
    	
    	// Call the service's creation method
    	customerServiceUnderTest.create(CUSTOMER_CODE, CUSTOMER_NAME);
    	
    	// Verification phase
    	Mockito.verify(customerDaoDouble).save(new CustomerDTO(CUSTOMER_CODE, CUSTOMER_NAME));
    	

    The previous test will fail if save is not invoked as a result of calling create or if it’s invoked with a parameter different [1] from the specified parameter (new CustomerDTO…).

Summary

The technique of testing with mock objects is often misunderstood.
A common mistake is forgetting to install the test double in place of the real object. In this scenario the test double remains unused and it’s the real object that gets called.
I’ve also seen tests exercising the mocked methods instead of the methods in the class under test. Since the implementation of the mocked methods is trivial, such tests are of no value.
But succeeding is really easy if you follow these steps in your use of Mockito:

  1. Create the test double (or mock object, stretching a little bit the meaning).
  2. Set up the double’s behaviour. Optional step, usually done when the methods return some value.
  3. Replace the real object with its corresponding test double.
  4. Exercise the software under test.
  5. Verify. It can be a traditional JUnit/Hamcrest assertion, a Mockito verification, or even a combination of both.

Lastly, some subjects have only been briefly addressed. I expect to elaborate a little bit on them in forthcoming articles. Stay tuned!

1. different according to equals, more on this in forthcoming articles

Concurrency testing with tempus-fugit

Development for a highly concurrent environment is a tough technique. A programme with a good coverage of passing unit tests can fail miserably in production due to concurrency issues.

In this post I’ll be discussing a pragmatic approach to concurrency testing with Junit tests and the tempus-fugit library.

This library provides us with many utilities that help dealing with typical concurrency aspects. You can read about those in the official documentation, but now I’m going to talk about a technique that I find particularly useful and easy to apply: what they call load/soak tests.

One of the typical characteristics of concurrency errors is the indeterminism. Errors are hard to reproduce because they depend on the threads running in a particular order.

The load/soak tests provided by tempus-fugit allow us to run a number of threads high enough to maximise the likelihood of raising any concurrency issues.

Let’s illustrate this with an example.

First of all, let start with a naïve class that performs a basic XML schema validation on an XML string  [1]:

public class MySchemaValidator {

	private Validator validator;

	public MySchemaValidator() {

		final String simpleSchema = "<?xml version='1.0'?>"
				+ "<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>"
				+ "<xs:element name='note'>"
				+ "	<xs:complexType><xs:sequence>"
				+ "		<xs:element name='to' type='xs:string'/>"
				+ "		<xs:element name='from' type='xs:string'/>"
				+ "		<xs:element name='heading' type='xs:string'/>"
				+ "		<xs:element name='body' type='xs:string'/>"
				+ "	</xs:sequence></xs:complexType>"
				+ "</xs:element></xs:schema>";
		final StreamSource svgXsdSource = new StreamSource(new StringReader(simpleSchema));
		try {

			validator = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
							.newSchema(svgXsdSource).newValidator();

		} catch (final SAXException e) {
			// Not expected to happen
			e.printStackTrace();
		}
	}

	public boolean isValid(final String xml) {
		try {

			validator.validate(new StreamSource(new StringReader(xml)));
			return true;

		} catch (final Exception e) {
			e.printStackTrace();
			return false;
		}
	}
}

This class exhibits some characteristics that leave to potentical concurrency issues:

  • Mutable state. The class has a mutable instance variable (validator).
  • These data are shared and non-thread-safe. As an instance variable, it can be accessed by multiple threads. Furthermore, the Validator class is not thread-safe, as it’s stated in its javadoc.

Before digging deeper into the concurrency issues, let’s write some basic JUnit tests for the class:

  1. A test that make sure that our isValid method returns true when a valid XML string is received
  2. A test that make sure that our isValid methos returns false when an invalid XML string is received
public class MySchemaValidatorTest {

	private MySchemaValidator validatorUnderTest;

	@Before
	public void setUp() throws Exception {
		validatorUnderTest = new MySchemaValidator();
	}

	@Test
	public void testIsValidInvalidXml_shouldReturnFalse() throws IOException {

		final String invalidXml = "<html></html>";

		Assert.assertFalse(validatorUnderTest.isValid(invalidXml));
	}

	@Test
	public void testIsValidValidXml_shouldReturnTrue() throws IOException {

		final String validXml = "<?xml version=\"1.0\"?>"
				+ "<note>"
				+ "	<to>Tove</to>"
				+ "	<from>Jani</from>"
				+ "	<heading>Reminder</heading>"
				+ "	<body>Don't forget me this weekend!</body>"
				+ "</note>";

		Assert.assertTrue(validatorUnderTest.isValid(validXml));
	}
}

After running these tests, we confirm that everything looks OK. Or so we think.
(By the way, if anyone is intrigued about the name I gave to the test methods, I wholeheartedly recommend reading this gem about XUnit testing: xUnit Test Patterns by G. Meszaros.)

Unfortunately, If we were to use our class in a concurrent environment, we’d start to see some weird behaviour.

This is the moment to write some load/soak tests with the help of the tempus-fugit library. This involves just two easy steps:

  1. Including in our test class a JUnit rule provided by tempus-fugit: ConcurrentRule.
  2. Annotating our test methods with @Concurrent, which receives the number of desired concurrent threads as argument.

If we’re using Maven, we’ll need the following dependency to use the library:

    <dependency>
      <groupId>com.google.code.tempus-fugit</groupId>
      <artifactId>tempus-fugit</artifactId>
      <version>1.0</version>
      <scope>test</scope>
    </dependency>

Now we’re ready to write our concurrent tests:

public class MySchemaValidatorConcurrencyTest {

	@Rule
	public ConcurrentRule concurrently = new ConcurrentRule();

	private MySchemaValidator validatorUnderTest = new MySchemaValidator();

	@Test
	@Concurrent(count = 100)
	public void testIsValidInvalidXml_shouldReturnFalse() throws IOException {

		final String invalidXml = "<html></html>";

		Assert.assertFalse(validatorUnderTest.isValid(invalidXml));
	}

	@Test
	@Concurrent(count = 100)
	public void testIsValidValidXml_shouldReturnTrue() throws IOException {

		final String validXml = "<?xml version=\"1.0\"?>"
				+ "<note>"
				+ "	<to>Tove</to>"
				+ "	<from>Jani</from>"
				+ "	<heading>Reminder</heading>"
				+ "	<body>Don't forget me this weekend!</body>"
				+ "</note>";
		Assert.assertTrue(validatorUnderTest.isValid(validXml));
	}
}

You may have noticed that we have initialised the validatorUnderTest inlined instead of using a set-up method. The reason is to have all the 100 threads to access the same instance, instead of having a different object for each thread.

If we run our newly created test class, we’ll realise that the tests are failing now, as we’ve been fearing. The console will have shown messages like this one:

        FWK005 parse may not be called while parsing.

It’s time to change our original class in order to synchronise the access to the shared mutable field (validator).

public class MySchemaValidator {

	private volatile Validator validator;

	public MySchemaValidator() {

		final String simpleSchema = "<?xml version='1.0'?>"
				+ "<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema'>"
				+ "<xs:element name='note'>"
				+ "	<xs:complexType><xs:sequence>"
				+ "		<xs:element name='to' type='xs:string'/>"
				+ "		<xs:element name='from' type='xs:string'/>"
				+ "		<xs:element name='heading' type='xs:string'/>"
				+ "		<xs:element name='body' type='xs:string'/>"
				+ "	</xs:sequence></xs:complexType>"
				+ "</xs:element></xs:schema>";
		final StreamSource svgXsdSource = new StreamSource(new StringReader(simpleSchema));
		try {

			validator = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
							.newSchema(svgXsdSource).newValidator();

		} catch (final SAXException e) {
			// Not expected to happen
			e.printStackTrace();
		}
	}

	public boolean isValid(final String xml) {
		try {
			final StreamSource xmlSource = new StreamSource(new StringReader(xml));

			synchronized (validator) {

				validator.validate(xmlSource);

			}
			return true;

		} catch (final Exception e) {
			e.printStackTrace();
			return false;
		}
	}
}

The most relevant changes are highlighted. Explaining the reasons behind these changes is not the goal of this post. If you need more information about it, this subject is clearly addressed on books like Effective Java or Concurent Programming in Java.

That’s all. Hopefully our concurrent tests are passing now and our class is ready for a highly concurrent environment.

I hope you find this post useful. Please, don’t hesitate in sharing your thoughts with the rest of us.

 

1. The sample XML schema and XML document are extracted from http://www.w3schools.com/xml/schema_intro.asp