Spring Book – Chapter 7 – Testing

Unit Testing with Mocks

I don’t find a convincing reason for switching to mocking frameworks from hand written stubs explained in previous sections. Nor do we need other frameworks in the market, but using mocking frameworks makes lives of an application developer much easier and simpler to some extend for sure.

Few points which come to mind in this regard, mainly the fact that after a while your tests become incomprehensible with your hand written test stubs.  In other words, you write code to stub, or return values depending on what happens which takes both time and effort. A mocking framework can do all this in a matter of lines. The benefits of a mocking framework are:

  • Easier (yes it is subjective)
  • Less Code
  • Follows DRY (Don’t Repeat Yourself)

According to Martin Fowler’s article “Mocks Aren’t Stubs” (http://martinfowler.com/articles/mocksArentStubs.html), the basic difference between mock and stub can be summarized as:

  • A stub’s job is to return known results to all calls send to it.
  • A mock additionally expects calls to come in a specific order, with specific parameters, and will throw an exception when these expectations are not met.

There are some error conditions that cannot be tested using stubs. On the other hand, tests using mocks are often much less stable. While stubs can be written manually with reasonable effort, mocks would require far more work. In addition, a good mocking framework can make writing stubs faster and easier as well.

There are various steps in executing a test using mocks. They are:

  • Using a mock library, generate a mock object.
  • According to the scenario required for testing, record a mock with the expectation needed. Identify the methods to be called and the values to be return in this step.
  • Execute the scenario.
  • Verify that the mock expectations are met.

Martin Fowler

He is an author, speaker, and loud-mouth on the design of enterprise software. He works for ThoughtWorks, a software delivery and consulting company. He popularized the term Dependency Injection (DI) as a form of Inversion of Control (IoC).

Mock Libraries

Libraries that give us an easy way to create mocks are called mock libraries/frameworks. Different frameworks provide their own ways to define the expectations and a variety of features to check the tested object’s behavior. Some of the well-known frameworks are listed below. These need not be the best in the industry nor the does the order reflect any implied priority of importance. Among the available mock frameworks, I will be giving an overview of the following in some detail.

  • EasyMock
  • jMock
  • Mockito

Apart from the above mock frameworks, there are other frameworks like SevenMock, rMock, Unitils, Mochachino, PowerMock etc. available in the market which can also be used for doing unit testing using mocks in your application.

Mocking frameworks tend to become different according to the mocking approach they take. According to the approach they take they tend to have advantage and disadvantages. Generally we can classify any mocking frameworks into two categories based on this. They are:

  • Proxy – Using the Java Reflection API to create the mock object
  • Remapping Class – Using Java Instrumentation API to remap the class in the class loader

EasyMock

One of the very popular mocking frameworks available in the industry as of now. It is used extensively in the Spring framework for various testing requirements.

EasyMock provides three different ways to instantiate mock objects accordingly its behavior changes. They are:

  • EasyMock.createMock() – doesn’t verify the order in which methods are called. When any exception happens, throws AssertionError.
  • EasyMock.createStrictMock() – it verifies the order in which methods are called. In case of any errors during method execution throws AssertionError.
  • EasyMock.createNiceMock() – doesn’t verify the order in which methods are called. In case of any errors during method execution return appropriate empty values.

The third option can be used for creating stubs but first and second option can only be used for creating pure mocks.

Listing 7-4. Example test class showing the usage of EasyMock to create mock objects for testing

[java]import static org.easymock.classextensions.EasyMock.*;

public class CustomerServiceTests{

private CustomerRepository customerRepository = createMock(CustomerRepository.class);

private CustomerService customerService = new CustomerServiceImpl(customerRepository);

@Test

public void customerExistsTest(String user){

expect(customerRepository.getCustomer(“john”)).andReturn(new Customer(“john”,”12345”));

replay(customerRepository);

boolean result = customerService.customerExists(“john”);

assertTrue(result);

verify(customerRepository);

}

}[/java]

In Listing 7-4, when expect method is called, the mock object is not created. It just records the expected method which has to be called. The actual mock object is created and loaded when replay method is called. When calling verify method it just makes sure that no method call has been omitted while executing this test case.

Various features of EasyMock can be summarized as follows:

  • Can be used to mock interfaces, abstract classes and concrete classes.
  • While mocking final classes, throws exception.
  • When mocking final and static methods, it actually delegates the call to the actual implementations
  • Mock objects created can be converted from one type to another (default, strict and nice)

jMock

jMock focuses on explicitly specifying behavior of the mocks using a specialized DSL (Domain Specific Language) embedded in the Java code. jMock instantiates both stub and mock objects in the same way. It can mock interfaces using an instance of the org.jmock.Mockery class. The test case class must be annotated with @RunWith(JMock.class) for JUnit4 which is shown in Listing 7-6 below.

Even though jMock is also a well-known framework, in my opinion it has cumbersome syntax and doesn’t provide any additional features to compete with the other mocking frameworks like EasyMock or Mockito.


Listing 7-5. Example test class showing the usage of jMock to create mock objects for testing

[java]import org.jmock.Mockery;

public class CustomerServiceTests{

Mockery context = new Mockery();

private CustomerRepository customerRepository = context.mock

(CustomerRepository.class);

private CustomerService customerService = new CustomerServiceImpl(customerRepository);

@Test

public void customerExistsTest(String user){

context.checking(new Expectations() {{

oneOf(customerRepository). getCustomer ("john");

will(returnValue(new Customer(“john”,”12345”)));

}});

customerService.customerExists(“john”);

}

}[/java]

Listing 7-6. @RunWith annotation used in case of JUnit4

[java]@RunWith(JMock.class)

public class ListTest {

Mockery context = new JUnit4Mockery();

@Test

public void doMockInterface() {

List mockList = context.mock(List.class);

}

@Test

public void doMockClass() {

ArrayList mockList = context.mock(ArrayList.class);

}

}[/java]

By default mocked objects are strict. However, it is possible to change this behavior by declaring expectations by using either ignoring or allowing as shown in Listing 7-7. These two approaches are one and the same and one can choose the method that best expresses the purpose you are looking for in your application.

Listing 7-7. Usage of ignoring and allowing in jMock

[java]context.checking(new Expectations() {

{

ignoring(mockOne);

allowing(mockTwo);

}

});[/java]

The various features of jMock library can be summarized as below:

  • Mocked objects are strict by default
  • Let’s you mock interfaces, abstract classes and concrete classes
  • Throws exception when mocking final classes
  • Similar to EasyMock, it delegates to actual implementation when mocking final and static methods
  • Returns default values for mocked methods
  • Makes it quick and easy to define mock objects.
  • Let’s you precisely specify the interactions between your objects.
  • Plugs into your favorite test framework.
  • Easy to extend.

Mockito

Mockito does not make any difference between mock and stub objects. One can obtain a mock object using the Mockito.mock() method as shown in Listing 7-8.

To create a stub or a mock, use mock(class). Then use when(mock).thenReturn(value) to specify the stub value for a method. If you specify more than one value, they will be returned in sequence until the last one is used, after which point the last specified value gets returned.

Listing 7-8. Example test class showing the usage of Mockito to create mock objects for testing

[java]import static org.mockito.Mockito.*;

public class CustomerServiceTests{

private CustomerRepository customerRepository = mock(CustomerRepository.class);

private CustomerService customerService = new CustomerServiceImpl(customerRepository);

@Test

public void customerExistsTest(String user){

when(customerRepository.getCustomer(“john”)).thenReturn(new Customer(“john”,”12345”));

boolean result = customerService.customerExists(“john”);

assertTrue(result);

verify(customerRepository).getCustomer(“john”);

}

}[/java]

The various features of Mockito library can be summarized as below:

  • Mocked objects are not strict by default
  • With just an annotation you can mock objects
  • Let’s you mock interfaces, abstract classes and concrete classes
  • Throws exception when mocking final classes
  • Similar to EasyMock and jMock, it delegates to actual implementation when mocking final and static methods
  • Returns default values for mocked methods
  • Allows to specify how many times you expect a certain method to be called
  • With doAnswer() method you have provision of adding logic to your stubbed implementation

Page Visitors: 5830

The following two tabs change content below.
Tomcy John

Tomcy John

Blogger & Author at javacodebook
He is an Enterprise Java Specialist holding a degree in Engineering (B-Tech) with over 10 years of experience in several industries. He's currently working as Principal Architect at Emirates Group IT since 2005. Prior to this he has worked with Oracle Corporation and Ernst & Young. His main specialization is on various web technologies and acts as chief mentor and Architect to facilitate incorporating Spring as Corporate Standard in the organization.
Tomcy John

Latest posts by Tomcy John (see all)

6 thoughts on “Spring Book – Chapter 7 – Testing

  1. I wanted to put you the little note to finally thank you over again with your wonderful knowledge you’ve documented on this page. This is really shockingly generous of people like you to deliver publicly all most people would’ve made available as an e book to earn some cash for their own end, primarily considering the fact that you might have tried it if you wanted. Those tips likewise acted like the fantastic way to be sure that someone else have similar zeal just as my own to realize many more in regard to this issue. I’m certain there are several more pleasurable sessions up front for people who see your blog.

  2. Hello There. I found your blog using msn. This is an extremely well written article. I will be sure to bookmark it and come back to read more of your useful info. Thanks for the post. I will certainly comeback.

Leave a Reply

Your email address will not be published. Required fields are marked *