Mocks & Spies
We all know how JUnit is important
for making sure that our code is doing what it is supposed to be doing. Mocks
are integral part of JUnit. When you test a class you usually want to isolate
that class from the rest of the world and concentrate on that class. To do that
you need to use Mocks. Mocks let you mimic the components that your tested
class deals with, without really needing to make sure they are really there.
You can ‘teach’ a mock to act in ways you need and by doing so test your class
to make sure it actually doing the right stuff based on the input data and the
mocks behavior.
There are a few Mock frameworks in
Java. In this post I will describe the way to work with PowerMock. PowerMock
lets you work with mocks and spies.
Mock
When we deal with mocks, we can
either mock an instance for its non-static public/protected/private methods or
mock the static methods of a class.
Mocking an instance
Mocks are created when you need to completely
replace an instance.
Guidelines:
1.
There’s
no instance of the mocked class, rather there is an instance of a proxy mock
that represents it.
2.
The
mock can mock a concrete class or an interface.
3.
When
a method that is not mocked is called:
a. If the called method returns a value, then the
returned value will be the return type’s default value.
b. In
case of a ‘void’ method nothing is done.
4.
To
mock a method you should do the following
The preferred syntax is:
a. To
mock a method with a return value:
PowerMockito.doReturn(value).when(mock).method(arguments);
b. To
mock a void method
PowerMockito.doNothing().when(mock).method(arguments);
Example:
Spy
Spying (partial mock) after an
instance
Spy is created when you need to have
a ‘partial mock’. That means when you have a real instance and you need
to call at least one of its real methods and to mock other(s).
1.
A
Spy, unlike mock, works on a real instance.
2.
By
default a method that is called will activate the real method.
3.
To
mock a method you must do the following:
a. To
mock a method with a return value: PowerMockito.doReturn(value).when(spy).method(arguments);
b. To
mock a void method
PowerMockito.doNothing().when(spy).method(arguments);
Note that you first need to declare the return value and then the method, otherwise the method will be activated.
Spy: Mocking Private Methods
Mocking private methods is done a
bit differently and for that we need to do the following:
1.
Add
the PrepareForTest annotation with the class/classes that we need to
mock their private method(s), for example:
2.
Use
the following syntax, for example:
Note, you will
need to add ‘throws Exception’ to your test declaration.
3. Verification
Example 1:
Verify
that the method “privateMethod” was called for ‘spy’
Example 2:
Verify that the method “privateMethodOther” was never called for ‘spy’
Mock: Mocking Static Methods
Mocking private methods is done a
bit differently and for that we need to do the following:
1.
Add
the PrepareForTest annotation with the class/classes that we need to
mock their static methods, for example:
2.
Use
the following syntax, for example:
Note, when you
need to mock static methods, you are mocking ALL the static methods of the
class.
3.
Mocking
a static method:
4.
Verification,
you can only check that static methods were called once like that:
Note that
verification on static methods is usually not needed.
Spy: Mocking Static Methods
Mocking private methods is done a
bit differently and for that we need to do the following:
Add
the PrepareForTest annotation with the class/classes that we need to
mock their static methods, for example:
Use
the following syntax, for example:
Note, when you
need to mock static methods, you are mocking ALL the static methods of the
class.
3 Mocking
a static method:
Calls
to a non-mocked static method will activate that method.
Verification,
you can only check that static methods were called once like that:
Note that
verification on static methods is usually not needed.
Examples
Suppose we have the following
‘TestedClass’ that we wish to test. The class has public and private methods
(static and non-static):
Test declaration
Mock- Mocking a public non-static
method
By default
the mock would return null since that is the default value for the
returned type ‘String’. We override that by ‘teaching’ the mock to return
‘testPublic’:
Mock - Mocking a private non-static method
Mock - Mocking a public static method
Spy – mocking a public non-static
method
Note:
1. The
spy works on a real instance of ‘TestedClass’.
2. You
need to declare the ‘doReturn’ first, otherwise the real method ‘publicMethod’
will be activated.
3. When
a non-mocked method is called (‘publicMethodOther’) the real method is invoked.
Spy – Mocking a private
non-static method
Note
1. The
syntax is the same for mocks and spies.
2. The
syntax that is using the method’s name.
3. The
test might throw exception.
Spy – Mocking static methods
We spy over the class ‘TestedClass’
since we want to mock only ‘testPublicStatic’ but not the other static method
‘publicStaticMethod1’:
Spy – mocking private static method
In this case we have a spy, ‘spy’,
that spies on an instance of ‘TestedClass’ and we also spy on the static
methods of ‘TestedClass’. We use spy for
the static methods since we want only to mock the private static method
‘privateStaticMethod’ while other static methods should behave as usual.
Spy – combination
A spy, mock on all static methods
and mocking a private method of the spy: