Beginners guide to using Mockito and PowerMockito to unit test Java
Background
Lately, I have been writing Java at work, and it is something I havenât done in years. I have been completely oblivious to the current ecosystem.
When it came time to write some unit tests for the code I was working on I wasnât given a ton of direction. Our team had classically created overriden classes to perform stubbing. I wasnât 100% pleased with this so I decided to explore what was out there.
Thus I stumbled across Mockito and PowerMockito and was very happy with the results.
Setup
I have been using Gradle for building at work so thatâs what Iâm going to use in my example. We need to add these two lines to our dependencies:
testCompile group: 'org.mockito', name: 'mockito-all', version: '1.9.5'
testCompile "org.powermock:powermock-mockito-release-full:1.6.1"
After we refresh gradle, it will pull these dependancies down for testing.
Example Classes
I have a
so enjoy my puppy themed source code ;)
Human.java
public class Human {
public String name;
public Puppy puppy;
public Human(String name) {
this.name = name;
}
public void buyPuppy(String name){
puppy = Puppy.createPuppy(name, this);
}
public void walkWithPuppy() {
puppy.goOnWalk(15);
}
public static void main(String[] args) {
Human john = new Human("John");
john.buyPuppy("Gatsby");
john.puppy.performPuppyTasks();
john.walkWithPuppy();
}
public void isSoHappy() {
System.out.println("Yay!");
}
}
Puppy.java
import java.util.Random;
public class Puppy {
private final String name;
public Human owner;
private int energyLevel;
private Random puppyRandomness;
public Puppy(String name, Human owner){
this.name = name;
this.owner = owner;
energyLevel = 100;
puppyRandomness = new Random();
}
public static Puppy createPuppy(String name, Human human) {
human.isSoHappy();
return new Puppy(name, human);
}
public void chaseTail(){
bark();
energyLevel -= getRandomInt(10);
}
public void bark(){
System.out.println("WOOF!");
}
public void goOnWalk(int length){
performBusiness();
energyLevel -= length;
wipeOffFeet();
}
public void wipeOffFeet(){
System.out.println("Paws on fleek");
}
private void performBusiness() {
System.out.println("When you gotta go you gotta go...");
}
public void performPuppyTasks(){
eat();
sleep();
play();
}
private void eat(){
energyLevel+= getRandomInt(10);
}
private void sleep() {
energyLevel+= getRandomInt(10);
}
private void play() {
energyLevel-= getRandomInt(10);
}
private int getRandomInt(int bounds){
return puppyRandomness.nextInt(bounds);
}
public String getName() {
return name;
}
}
The Test Class
This is the test class. Notice how it extends PowerMockTestCase
and how we annotate it with:
@PrepareForTest({Puppy.class})
@RunWith(PowerMockRunner.class)
PuppyTest.java
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.testng.PowerMockTestCase;
import org.powermock.reflect.Whitebox;
import static org.mockito.Mockito.times;
@PrepareForTest({Puppy.class})
@RunWith(PowerMockRunner.class)
public class PuppyTest extends PowerMockTestCase {
@Test
public void testCreatePuppy() throws Exception {
//Mocking
Human human = Mockito.mock(Human.class);
Puppy puppy = Puppy.createPuppy("Woofer", human);
assert(puppy != null);
assert(puppy.getName().equals("Woofer"));
//Verifying
Mockito.verify(human, times(1)).isSoHappy();
}
@Test
public void testChaseTail() throws Exception {
Human human = Mockito.mock(Human.class);
//Spying
Puppy puppy = Mockito.spy(new Puppy("Woofer", human));
Mockito.doNothing().when(puppy).bark();
puppy.chaseTail();
Mockito.verify(puppy, times(1)).bark();
}
@Test
public void testGoOnWalk() throws Exception {
Human human = Mockito.mock(Human.class);
//Power Spying
Puppy puppy = PowerMockito.spy(new Puppy("Woofer", human));
PowerMockito.doNothing().when(puppy, "performBusiness");
//Can combine regular and power
Mockito.doNothing().when(puppy).wipeOffFeet();
puppy.goOnWalk(15);
Mockito.verify(puppy, times(1)).wipeOffFeet();
}
@Test
public void testBuyPuppy() throws Exception {
//Mocking static
PowerMockito.mockStatic(Puppy.class);
Human human = new Human("John");
Puppy puppy = Mockito.mock(Puppy.class);
//Static mocking and matchers
PowerMockito.when(Puppy.createPuppy(Mockito.eq("Woofer"), Mockito.any(Human.class))).thenReturn(puppy);
human.buyPuppy("Woofer");
assert(human.puppy != null);
}
@Test
public void testEat() throws Exception {
Human human = Mockito.mock(Human.class);
Puppy puppy = PowerMockito.spy(new Puppy("Woofer",human));
//Get private variables
int energy = Whitebox.getInternalState(puppy, "energyLevel");
//Call private methods
Whitebox.invokeMethod(puppy, "eat");
int energyAfterwards = Whitebox.getInternalState(puppy, "energyLevel");
System.out.println(energy + " > " + energyAfterwards);
assert(energy <= energyAfterwards);
}
}
Mocking
Mocking is something we do to classes to make our life simplier while unit testing. Essentially, it turns off all the functionality of a class. This is useful when we want to test methods that call functionality on other objects.
Here is a test that uses mocking.
@Test
public void testCreatePuppy() throws Exception {
//Mocking
Human human = Mockito.mock(Human.class);
Puppy puppy = Puppy.createPuppy("Woofer", human);
assert(puppy != null);
assert(puppy.getName().equals("Woofer"));
//Verifying
Mockito.verify(human, times(1)).isSoHappy();
}
Notice that we also use Mockito.verify() to verify the method was still called only once even though it does not actually do anything.
Spying
Lets suppose we want a class to do everything it would normally do EXCEPT for one or more specific methods. This is where spying and PowerMockito comes into place. We can spy on an object and specify when methods are called to do other things.
Here is a test using spying.
@Test
public void testChaseTail() throws Exception {
Human human = Mockito.mock(Human.class);
//Spying
Puppy puppy = Mockito.spy(new Puppy("Woofer", human));
Mockito.doNothing().when(puppy).bark();
puppy.chaseTail();
Mockito.verify(puppy, times(1)).bark();
}
Again, notice that we can still verify that bark was called even though we stubbed it out.
Power spying to stub private methods
Lets suppose we want to spy on an object but we want a private method to do something else. PowerMockito has you covered!
@Test
public void testGoOnWalk() throws Exception {
Human human = Mockito.mock(Human.class);
//Power Spying
Puppy puppy = PowerMockito.spy(new Puppy("Woofer", human));
PowerMockito.doNothing().when(puppy, "performBusiness");
//Can combine regular and power
Mockito.doNothing().when(puppy).wipeOffFeet();
puppy.goOnWalk(15);
Mockito.verify(puppy, times(1)).wipeOffFeet();
}
Notice how on line 8 we are mixing Mockito with PowerMockito. Not only can we do this, it is encouraged. PowerMockito is a permgen memory hog and creates tons of classes. Whenever we can use Mockito over PowerMockito, we should!
Stubbing static methods
Lets suppose you have a class with a static method and we want to stub out its behaviour. PowerMockito has a way to do this.
@Test
public void testBuyPuppy() throws Exception {
//Mocking static
PowerMockito.mockStatic(Puppy.class);
Human human = new Human("John");
Puppy puppy = Mockito.mock(Puppy.class);
//Static mocking and matchers
PowerMockito.when(Puppy.createPuppy(Mockito.eq("Woofer"), Mockito.any(Human.class))).thenReturn(puppy);
human.buyPuppy("Gatsby");
assert(human.puppy != null);
}
Also notice we are specifying that we need the first argument to be âWooferâ but we will accept any Human.class for the second arguement.
Other WhiteBox fun
If you need to access any private members or invoke private methods we can use WhiteBox which is provided with PowerMockito.
@Test
public void testEat() throws Exception {
Human human = Mockito.mock(Human.class);
Puppy puppy = PowerMockito.spy(new Puppy("Woofer",human));
//Get private variables
int energy = Whitebox.getInternalState(puppy, "energyLevel");
//Call private methods
Whitebox.invokeMethod(puppy, "eat");
int energyAfterwards = Whitebox.getInternalState(puppy, "energyLevel");
System.out.println(energy + " > " + energyAfterwards);
assert(energy <= energyAfterwards);
}
On line 8 we invoke the private method âeatâ.
We could technically set a private variable via setInternalState(object, âvariableâ, value) or call a private method with parameters via invokeMethod(object, âprivateMethodâ, parameter).
Conclusion
So far we have mocked and stubbed via Mockito, mocked and stubbed private methods via PowerMockito, and got into all sorts of trouble with Whitebox. If you are feeling powerful and a bit naughty, I think you are doing it right. You can over abuse these libraries and make tests useless, or you can remove the bare minimum to get appropriate code coverage.
I had a blast learning all of this and I hope you do too. Stay frosty, and try to enjoy unit testing ;)
How I Used Swift to Build a Map Based Location Tracker for iOS
Anything location based is really cool, and having that information displayed on a map is even better! So ⌠lets track our location and plot it on a map :)
The good news about this tutorial is there is very little code! The flip side is, we will have to do some extra setup. Lets begin!
Preface: Iâm still very much a beginner to Swift, and I am just sharing my journey to help out other beginners :) Iâm also using Xcode beta 5 for this.
Setup
Setting up the project
File -> New -> Project
Then select
iOS -> Application -> Single View Application
Give it a name and make sure we are using the language Swift :)

Open our Main.storyboard file.

Show the document outline. There is a little handle in the lower left window of the storyboard to do this.

Highlight our View Controller for this scene, and navigate to the attributes inspector.

For this project, we are going to set the size to be âRetina 4-Inch Full Screenâ and Iâm going to set the Orientation to Portrait.
Setting up the MapKit View
Apple has already provided us with a map view. So we just need to drag one into our scene.

Setting up the label
We are also going to have a label to display some debug information about our location. Drag one into the scene as well.

Feel free to adjust the attributes in the inspector to make the label look like mine. I centered the text, gave the label 3 lines, and used the awesomely cool font âHelvetica Neue Thinâ with a font size of 12 (incorrectly â17.0â in screen shot).
Creating the IBOutlets
Now that we have our mapview and label, we are going to drag them into our ViewController.swift code so we can control them with code.
We want to switch to assistant editor (the view that looks like a suit and bow tie in the upper right), and then âright click dragâ our MKMapView into our ViewController.swift file.


We also want to right click, and drag from the Label to our ViewController.swift file.


You will see some errors, but this will go away once we fix our imports. If you are dying to fix this now, add this under import UIKit
import CoreLocation
import MapKit
Editing the info.plist
We need to add 2 keys to our info.plist file, which is located in the âSupporting Filesâ folder. The two keys are NSLocationWhenInUseUsageDescription
and NSLocationAlwaysUsageDescription
. Right click on âInformation Property Listâ, click Add Row
, and manually enter these two keys.

The final form should look like this:

Simulating your location
The last thing I want to mention is there is no way (I saw) to have the iOS simulator aware of your actual location. However, the simulator DOES allow you to fake this data. Make sure you have a good simulation selected or else this program will just show an empty map.
Once you have the simulator going select a location!!!

ViewController.swift and Full Code
Phew! Thank goodness all that setup is out of the way. Time for the code!