Mocking

Installation

If you are using maven, you can add following dependency to your project.

01
02
03
04
05
06
<dependency>
    <groupId>org.unitils</groupId>
    <artifactId>unitils-mock</artifactId>
    <version>3.4.2</version>
    <scope>test</scope>
</dependency>

If you are not using maven you can download the unitils-with-dependencies.zip. The required jar, unitils-mock.jar, can be found in the unitils-mock folder, the required dependencies, in the unitils-mock/lib folder.

Creating mocks

Creating a mock is easy. If your test is unitils-enabled you just have to create a field of type Mock and unitils will automatically create a mock and inject it into the field. The type to mock is specified as a generic type.

01
02
03
04
66
public class MyServiceTest extends UnitilsJUnit4 {
 
    private Mock<MyService> myServiceMock;
 
}

If you don't want to unitils-enable your test, you can also create the mocks directly in your test by creating an instance of MockObject.

01
02
03
04
@Before
public void initialize() {
    myServiceMock = new MockObject<MyService>(MyService.class, this);
}

You can mock both interfaces and classes. In case a class is mocked, you also have the option to use a PartialMock. This is a special kind of mock that will invoke the original behavior of the class if you do not set a mock behavior. Some examples of how this works will be given later in the tutorial.

Defining and asserting mock behavior

There are 2 types of operations on a mock: behavior defining operations and asserting operations. These are 2 different functions of the mock. Before a test you typically setup some required behavior for a mock. After the test, you then assert that some of the methods of the mock have been called.

The mocks are lenient. If you do not define any behavior, unitils will perform a default behavior (see below). It's only when you do an assertion that unitils will verify that something has been called. You only have to assert things in your test that are of importance for your test. This will make your tests more maintainable and readable.

Defining behavior

Returning values
01
myServiceMock.returns("a value").someMethod();

This will return a value when someMethod is called on the myServiceMock instance.

Throwing exceptions
01
02
myServiceMock.raises(RuntimeException.class).someMethod();
myServiceMock.raises(new RuntimeException()).someMethod();

This will raise a RuntimeException when someMethod is called on the myServiceMock instance. You can pass the instance that needs to be thrown or just pass the exception class. An instance will then automatically be created (a default constructor is not needed).

Overriding behavior
01
02
03
04
05
06
myServiceMock.performs(new MockBehavior() {
    public Object execute(ProxyInvocation proxyInvocation) throws Throwable {
        // do something else
        return "a value";
    }
}).someMethod();

This will make the given mock behavior the behavior of someMethod. The return value of the execute method will then be returned by the mock. If you are overriding a void method, you can just return a null value.

Default behavior

You're not required to specify behavior. If no behavior was defined, Unitils will return a sensible default value.

  • 0 - for any primitive or primitive wrapper return value
  • empty ArrayList - for any List or Collection return value
  • empty HashSet - for any Set return value
  • empty HashMap - for any Map return value
  • empty array - for any array return value
  • null - for any object return value

Asserting behavior

Asserting that a method was invoked
01
myServiceMock.assertInvoked().someMethod();

This will verify that someMethod was invoked. This only matches one invocation. Multiple assertInvoked methods can be used to verify that multiple invocations were performed.

Asserting that a method was not invoked
01
myServiceMock.assertNotInvoked().someMethod();

This will verify that someMethod was not invoked. If you want to verify that an invocation only occurred once, you can first do an assertInvoked followed by an assertNotInvoked

01
02
myServiceMock.assertInvoked().someMethod();
myServiceMock.assertNotInvoked().someMethod();
Asserting that methods were invoked in a particular order
01
02
myServiceMock.assertInvokedInSequence().someMethod();
myServiceMock.assertInvokedInSequence().anotherMethod();

This will verify that someMethod was called followed by anotherMethod. Only the assertInvokedInSequence invocations will be checked on relative order. The order of assertInvoked methods is ignored.

Asserting that there were no other invocations

The MockUnitils.assertNoMoreInvocations method can be used if you want to make sure that the asserted invocations were the only invocations.

01
02
myServiceMock.assertInvoked().someMethod();
MockUnitils.assertNoMoreInvocations();

This will verify that someMethod was invoked and that it was the only invocation on any of the mocks.

When to define mock behavior

Mock behavior can be defined anywhere in your test. It only has to be there when the mock is actually used. You can for example define default behavior in your setup method. Using argument matching you can then even override the behavior with more specific behavior in your test method.

01
02
03
04
05
06
07
08
09
@Before
public void initialize() {
    userDaoMock.returns(defaultUser).findUserByName(null);
}
 
@Test
public void testMethod() {
    userDaoMock.returns(john).findUserByName("john");
}

Further in the tutorial we will discuss the argument matching in more detail. In short, unitils will always try to find the best matching invocation. A null argument value will be ignored, i.e it will match any object.

Mock chaining

It is possible to chain methods when defining or asserting mock behavior.

01
myServiceMock.returns(connection).createDataSource().getConnection();

This will return the given connection when getConnection() is called on the DataSource that is returned by the createDateSource() method. Behind the scenes unitils will automatically create a mock of type DataSource and define the getConnection() behavior on it.

You can do the same thing when asserting invocations:

01
myServiceMock.assertInvoked().createDataSource().getConnection();

This will assert that the getConnection() method was called on the DataSource that was returned by the createDataSource() method. This does not create a mock, it only asserts that a method was called. The mock behavior has to be defined like in the previous example.

Using mocks

In order to use the created mocks, we have to install them in the tested object (or wherever they will be used). You can do this manually by calling the appropriate setter methods or use unitils-inject to inject the mock directly.

Installing a mock using setter methods

01
02
03
04
05
06
07
08
09
10
11
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class MyServiceTest extends UnitilsJUnit4 {
 
    /* Tested object */
    private MyService myService;
 
    private Mock<MyDao> myDaoMock;
 
    @Before
    public void initialize() {
        myService = new MyService();
        myService.setMyDao(myDaoMock.getMock());
    }
 
    @Test
    public void testMethod() {
        // define behavior
        myDaoMock.returns("something").getSomething();
 
        // do the actual test
        boolean result = myService.doService();
 
        // assert results and invocations
        assertTrue(result);
        myDaoMock.assertInvoked().storeSomething("something");
    }
}

This test extends UnitilsJUnit4 and is therefore unitils-enabled. Unitils will automatically create and inject a mock instance in the myDaoMock field. In the before method, the test then creates the tested object and uses the setMyDao setter method to install the mock into that tested object. The testMethod then first defines some returns-behavior on the mock, executes the test and finally asserts that storeSomething with argument "something" was called during the test.

Notice that we used myDaoMock.getMock() as argument for the setter method.

11
myService.setMyDao(myDaoMock.getMock());

The myDaoMock instance is the object on which you define and assert behavior. The actual instance that is going to execute the behavior is the mock proxy and can be obtained by calling the getMock() method. The mock proxy is a dynamically generated implementation or sub-class of the required type, in this case MyDao. This proxy will intercept all invocations called on it, record them and if necessary execute the requested behavior.

Installing a mock using injection

If you use unitils-inject, the above test can be written as follows:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
public class MyServiceInjectTest extends UnitilsJUnit4 {
 
    @TestedObject
    private MyService myService;
 
    @InjectIntoByType
    private Mock<MyDao> myDaoMock;
 
    @Test
    public void testMethod() {
        // define behavior
        myDaoMock.returns("something").getSomething();
 
        // do the actual test
        boolean result = myService.doService();
 
        // assert results and invocations
        assertTrue(result);
        myDaoMock.assertInvoked().storeSomething("something");
    }
}

Unitils will see that the mock field has an InjectIntoByType annotation and inject the proxy of that mock into the object marked as TestedObject. The tested object will automatically be created.

This is not the only way you can inject mocks. You can, for example, also use injection without a TestedObject or inject mocks into static fields (like singletons). See the unitils-inject tutorial for more information.

Intercepting mock creation

The above way of injecting mocks is very powerful and easy, but sometimes applications are not coded in such a way that this is possible. It could be for example, that an application uses a service locator instead of dependency injection.

To help with this, an @AfterCreateMock annotation is provided that allows intercepting a mock immediately after its creation. The mock instance can then be used to register the mock in the service locator or perform some other task of configuration. For example:

01
02
03
04
@AfterCreateMock
void injectMock(Object mock, String name, Class type) {
    ServiceLocator.injectService(type, mock);
}

Scenario report

When an assertion fails you will get an AssertionError containing a report that consists out of 3 parts:

  • The reason why the assertion failed and where the assertion was made
  • A list of all observed invocations with the arguments at invocation time and the location where the invocation occurred
  • The same list of invocations but now with more details, like for example where the behavior was defined (if any)
java.lang.AssertionError: Expected invocation of MailService.sendMail(), but it didn't occur.
asserted at org.unitils.mock.UserNotificationServiceTest.notifyExpiredUsers(UserNotificationServiceTest.java:44)

Observed scenario:

1. userDaoMock.getUsersWithExpiredLicense() -> list1  .....  at org.unitils.mock.UserNotificationService.notifyExpiredUsersByMail(UserNotificationService.java:14)
2. mailServiceMock.sendMail("john@company.com", "subject", "body")  .....  at org.unitils.mock.UserNotificationService.notifyExpiredUsersByMail(UserNotificationService.java:16)
3. mailServiceMock.sendMail(string1, "subject", "body")  .....  at org.unitils.mock.UserNotificationService.notifyExpiredUsersByMail(UserNotificationService.java:16)


Detailed scenario:

1. userDaoMock.getUsersWithExpiredLicense() -> list1
- list1 -> [User<id=1, first="first", last="last", address=null, email="john@company.com">, User<id=2, first="first", last="last", address=null, email="jane@organization.org">]
- Observed at org.unitils.mock.UserNotificationService.notifyExpiredUsersByMail(UserNotificationService.java:14)
- Behavior defined at org.unitils.mock.UserNotificationServiceTest.notifyExpiredUsers(UserNotificationServiceTest.java:40)

2. mailServiceMock.sendMail("john@company.com", "subject", "body")
- Observed at org.unitils.mock.UserNotificationService.notifyExpiredUsersByMail(UserNotificationService.java:16)

3. mailServiceMock.sendMail(string1, "subject", "body")
- string1 -> "jane@organization.org"
- Observed at org.unitils.mock.UserNotificationService.notifyExpiredUsersByMail(UserNotificationService.java:16)

To keep the observed scenario report readable, large argument and result values will be replaced by a name. The full value can then be found in the detailed scenario. E.g. the list of users returned by the userDaoMock was too big to fit in the observed scenario and was therefore replaced by list1. The detailed scenario then displays the full content of list1.

All locations are formatted as stack trace element so you can click on them in your IDE.

You can display the observed and detailed scenario at any time by invoking the MockUnitils.logFullScenarioReport() method. This can help you write and debug tests. It's also possible to get only the observed or detailed scenario by calling MockUnitils.logObservedScenario() or MockUnitils.logDetailedObservedScenario() respectively.

01
02
03
04
05
06
07
08
userDaoMock.returns(asList(user1, user2)).getUsersWithExpiredLicense();
 
userNotificationService.notifyExpiredUsersByMail();
 
MockUnitils.logFullScenarioReport();
MockUnitils.logObservedScenario();
MockUnitils.logDetailedObservedScenario();
MockUnitils.logSuggestedAsserts();

The last log report statement, MockUnitils.logSuggestedAsserts(), is a small utility method that displays possible assertions for all void methods that were invoked during the test. If they are of value for your test, you could then add them to the test method (after verifying that they were correct!).

Suggested assert statements:

mailServiceMock.assertInvoked().sendMail("john@company.com", "subject", "body");
mailServiceMock.assertInvoked().sendMail("jane@organization.org", "subject", "body");

Argument matching

Unitils will try to find the mock behavior that has the best matching arguments. You only have to specify the behavior once. If it has matching arguments, the behavior will be invoked.

In the previous examples someMethod did not have any arguments. This means that unitils will always perform that behavior when someMethod is called. If you want to return/raise/perform something else for a following call, you can use the onceReturns, onceRaises and oncePerforms methods. The behavior then will be only invoked once and then removed from the mock. Matches for onceReturns, onceRaises and oncePerforms will always take precedence over any maching returns, raises or performs behavior.

01
02
03
myServiceMock.onceRaises(RuntimeException.class).someMethod();
myServiceMock.onceReturns("a value").someMethod();
myServiceMock.returns("another value").someMethod();

In this example, someMethod will first throw a runtime exception, then return a value and then continues returning another value for all following calls.

Most of the time you will not need the once behaviors. If there are arguments you can use these arguments to indicate when to execute the behavior.

01
02
userDaoMock.returns(user1).findUserById(1);
userDaoMock.returns(user2).findUserById(2);

In this case user1 will be returned when the id argument is 1 and user2 when the argument value is 2.

Ignoring arguments

If you are not interested in an argument value, you can just use null as argument value. Unitils will then ignore the actual argument value (it will always match).

01
userDaoMock.returns(asList(user1, user2)).getUsersInGroup(null);

This will return user1 and user2 for any argument value of getUsersInGroup. Note: this is only true for object values, primitive 0 values will be matched.

The rational behind this, is to make your tests as simple as possible. If an argument is not really of importance for a particular test, you can just leave it out.

If you explicitly want to check for a null argument value, you can use the isNull() argument matcher (see below).

Argument matchers

By default, arguments are matched as follows: if it's the same instance, there is of course a match. If it is not the same instance, we use reflection to match the to instances. If the argument is a collection, the order and actual type of the collection is ignored. You can for example use Arrays.asList() instead of an ArrayList.

01
userDaoMock.returns(asList(user1, user2)).getUsersForIds(asList(1L, 2L));

If this behavior is not sufficient, you can also use following argument matchers defined in the ArgumentMatchers class.

  • notNull - the argument is not null
  • isNull - the argument is null
  • same - the argument is the same instance
  • eq - the argument is equal using the equals method
  • refEq - the argument is equal using reflection
  • lenEq - the argument is equal using lenient reflection (see reflection assert)
  • any - the argument is any object of the given type
  • anyBoolean - the argument is a boolean
  • anyByte - the argument is a byte
  • anyShort - the argument is a short
  • anyChar - the argument is a char
  • anyInt - the argument is an int
  • anyLong - the argument is a long
  • anyFloat - the argument is a float
  • anyDouble - the argument is a double
01
02
03
userDaoMock.returns(asList(user1, user2)).getUsersForIds(any(List.class));
userDaoMock.returns(user1).findUserByName(notNull(String.class));
userDaoMock.returns(user1).findUserByName(isNull(String.class));

You do not have to specify argument matchers for all arguments (as in other frameworks). You only have to use argument matchers when you really need them. For example:

01
userDaoMock.returns(true).isExistingUser("first", "last", anyInt());
Creating your own argument matchers

It's not difficult to create a custom argument matcher. Just create a class that implements ArgumentMatcher and provide a static method somewhere that is annotated with @ArgumentMatcher.

The annotation will enable unitils to identify the method as argument matching method. It has to have a return value of the correct type so you can use it instead of an actual method argument. When the argument matcher method is called it should then register the argument matcher implementation in the ArgumentMatcherRepository.

Following is an example of a custom lessThan implementation that will match when a parameter is less than a given value. E.g method(lessThan(5)) will match for method(4) and not for method(6)

01
02
03
04
05
06
07
08
09
public class CustomArgumentMatchers {
 
    @ArgumentMatcher
    public static int lessThan(Integer lessThan) {
        LessThanArgumentMatcher argumentMatcher = new LessThanArgumentMatcher(lessThan);
        ArgumentMatcherRepository.getInstance().registerArgumentMatcher(argumentMatcher, getInvocationLineNr(CustomArgumentMatchers.class));
        return 0;
    }
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
public class LessThanArgumentMatcher implements ArgumentMatcher {
 
    private Integer lessThan;
 
    public LessThanArgumentMatcher(Integer lessThan) {
        this.lessThan = lessThan;
    }
 
    public MatchResult matches(Object argument, Object argumentAtInvocationTime) {
        Integer argumentAsInt = (Integer) argument;
        if (argumentAsInt != null && lessThan.compareTo(argumentAsInt) > 0) {
            return MATCH;
        }
        return NO_MATCH;
    }
}

Dummy objects

To be able to do a test you sometimes just need an instance of a class where the actual data or implementation is not of importance for your test. For example, you need a User instance that will be passed during invocations, but the actual values of the User instance are not used in your test. You just need a dummy implementation.

You can create a dummy object by annotating a field with the @Dummy annotation or by calling MockUnitils.createDummy. This will create a stub of the correct type that will ignore all method calls on it and will return default values for methods with return values. There doesn't have to be a default constructor. If your class does not have a no-argument constructor, you can still create an instance without having to provide all kinds of unnecessary values.

01
02
03
04
05
public class DummyTest {
 
    @Dummy
    private User dummyUser;
}

Partial mocks

A partial mock is a special kind of mock that will call the original behavior of the mocked class when no behavior was explicitly defined using returns, raises, performs or stub.

As an example, take following service implementation:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
public class SomeService {
 
    public int method1() {
        int result1 = method2();
        int result2 = method3();
        return result1 + result2;
    }
 
    protected int method2() {
        return 1000;
    }
 
    protected int method3() {
        return 2000;
    }
}

Suppose we created a partial mock for this class and define mock behavior for method2 but not for method3.

01
02
someServiceMock = new PartialMockObject<SomeService>(SomeService.class, this);
someServiceMock.returns(5).method2();

When method1 is now called on the someService mock proxy it will now return the mocked value 5 for method2 and the original value 2000 for method3.

Creating a partial mock

Creating a partial mock is similar to creating a regular mock. The only difference is that you now use PartialMock instead of Mock and PartialMockObject instead of MockObject.

If your test is unitils-enabled, just declare a field of type PartialMock with the type to mock as generic type.

01
02
03
04
34
public class PartialMockTest extends UnitilsJUnit4 {
 
    private PartialMock<SomeService> someServiceMock;
 
}

Unitils will automatically create the mock and inject it into the field.

If you don't want to unitils-enable your test, you can also create the mock directly by creating a new instance of PartialMockObject.

01
02
03
04
@Before
public void initialize() {
    someServiceMock = new PartialMockObject<SomeService>(SomeService.class, this);
}

When creating the mock, the default constructor will be called. If such a constructor does not exist, no constructor will be called and no fields will be initialized (all fields will be null or 0). If you still want to initialize your object, you can use a prototype to populate your mock.

01
02
03
04
05
06
07
08
09
10
public class SomeService {
 
    private int maxLength;
    private String defaultValue;
 
    public SomeService(int maxLength, String defaultValue) {
        this.maxLength = maxLength;
        this.defaultValue = defaultValue;
    }
}

A mock instance with correct values can then be created as follows:

01
02
03
04
05
@Before
public void initialize() {
    SomeService someServicePrototype = new SomeService(999, "default");
    someServiceMock = new PartialMockObject<SomeService>(someServicePrototype, this);
}

All fields of the given prototype instance will then automatically be copied into the new mock instance. This way you can still have a correctly initialized partial mock instance.

Behavior for a partial mock

All behavior and assertions you can do on a regular mock, you can also do on partial mock (PartialMock actually extends Mock). There is one extra behavior you can define on a partial mock: stub behavior.

Stubbing a method
01
someServiceMock.stub().method2();

If a method is stubbed, it will no longer do it's original behavior. If a non-void method is stubbed, it will return a default value. Asserting that the method was invoked, is still possible.

Mocking the tested object

This way of mocking can especially be useful for mocking methods of the tested object itself.

Factory and service locator methods

As a first example, suppose that your service has a factory method that returns something you would like to mock or uses the service-locator pattern to fetch a service.

01
02
03
04
05
06
07
08
09
10
11
15
16
17
18
19
29
public class MyService {
 
    public void doService() {
        DataSource dataSource = createDataSource();
        MyDao myDao = getMyDao();
 
        myDao.storeSomething("something", dataSource);
    }
 
    protected DataSource createDataSource() {
        // ... create a data source ...
    }
 
    protected MyDao getMyDao() {
        return ServiceLocator.getMyDao();
    }
}

We can then create a test for it that overrides these methods so that they return the mock instances.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
public class MyServiceTest extends UnitilsJUnit4 {
 
    @TestedObject
    private PartialMock<MyService> myService;
 
    private Mock<DataSource> dataSourceMock;
    private Mock<MyDao> myDaoMock;
 
    @Before
    public void initialize() {
        myService.returns(dataSourceMock).createDataSource();
        myService.returns(myDaoMock).getMyDao();
    }
 
    @Test
    public void testMethod() {
        myService.getMock().doService();
 
        myDaoMock.assertInvoked().storeSomething("something", null);
    }
}

In this example, we setup the default mock behavior in the before method: the mock will override the createDataSource and getMyDao method behavior and let them return the mocked DataSource and MyDao instances. The test method then performs the test on the tested object.

Notice the special myService.getMock() call. We've made our tested object a mock, so we need to get the mock proxy to call the actual test method.

This example test also shows that we can mock protected methods. A mock proxy is nothing more that an automatically created subclass, so we can access anything we would normally be allowed to access. In this case, the test class is in the same package (but other sources folder) as the tested object so the protected methods can be called.

Stubbing complex methods

Some methods are hard to test from a unit test. For example, methods that require network access or methods that require some kind of external service to be running. In these cases you would probably like to stub out the actual behavior of the method and just assert that the method was called with the expected arguments.

01
02
03
04
09
10
11
12
13
14
15
public class MailService {
 
    public void sendMessageToUser(String emailAddress) {
        // ... compose the mail etc ...
        doSendMail(emailAddress, subject, content);
    }
 
    protected void doSendMail(String emailAddress, String subject, String content) {
        // ... actual sending ...
    }
}

We can then write a test that stubs out the doSendMail method and just asserts that it has been called.

01
02
03
04
05
06
07
08
09
10
11
12
13
public class MailServiceTest extends UnitilsJUnit4 {
 
    private PartialMock<MailService> mailService;
 
    @Test
    public void testMethod() {
        mailService.stub().doSendMail(null, null, null);
 
        mailService.getMock().sendMessageToUser("some.user@mail.com");
 
        mailService.assertInvoked().doSendMail("some.user@mail.com", "some subject", "some content");
    }
}

Another example usage could be that there is some kind of complex behavior that is already covered in another set of tests. You can then stub the behavior and just assert that it was invoked with the correct argument values.

Testing abstract classes

Using a partial mock, it's easy to test the behavior of an abstract super class.

01
02
03
04
05
06
07
08
09
10
11
public abstract class AbstractService {
 
    public void doSomething() {
        // ...
        String result = doSomethingAbstract("a value");
        // ...
    }
 
    protected abstract String doSomethingAbstract(String argument);
}
// END SNIPPET: mailService

Just write a test that defines some behavior for the abstract methods and, if needed, assert that the methods were invoked during the test.

01
02
03
04
05
06
07
08
09
10
11
12
13
public class AbstractServiceTest extends UnitilsJUnit4 {
 
    private PartialMock<AbstractService> abstractService;
 
    @Test
    public void testMethod() {
        abstractService.returns("result").doSomethingAbstract(null);
 
        abstractService.getMock().doSomething();
 
        abstractService.assertInvoked().doSomethingAbstract("my value");
    }
}