Mockito mock static method example
In this article, I am going to show you how to mock static methods using Powermockito.
PowerMock is an open source mocking library. It extends the existing mocking frameworks, such as EasyMocks and Mockito, to add even more powerful features. One of them being mocking static methods. For more information, read Powermock – Mockito Integration Example.
My setup details:
- I am using Maven – the build tool
- Eclipse as the IDE, version Luna 4.4.1.
- JUnit is my testing framework.
- Add Mockito and PowerMockito dependencies to our
pom.xml
.
1. Dependencies in pom.xml
Our dependencies consist of:
junit
mockito-core
powermock-api-mockito
powermock-module-junit4
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javacodegeeks.testng.maven</groupId> <artifactId>testngMaven</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>2.0.5-beta</version> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-api-mockito</artifactId> <version>1.6.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock-module-junit4</artifactId> <version>1.6.2</version> <scope>test</scope> </dependency> </dependencies> </project>
2. System Under Testing (SUT)
In our example, an account holder requests for a mini statement. The account holder is represented by class AccountHolder
and the request is handled by method getMiniStatement()
.
AccountHolder:
package com.javacodegeeks.mockito; public class AccountHolder { private String name; private String accountNumber; public AccountHolder(String name, String accountNumber) { this.name = name; this.accountNumber = accountNumber; } public String getName() { return name; } public String getAccountNumber() { return accountNumber; } public Statement getMiniStatement() { AccountSummary accountSummary = AccountManager.getSummary(this); Transaction[] transactions = AccountManager.getTransactions(this); return new Statement(accountSummary, transactions); } }
The request is delegated to an AccountManager
which in turn will retrieve the account holder’s account summary and the transactions. For now, assume that the AccountManager
is not yet implemented so contains some dummy methods with UnsupportedOperationException
.
AccountManager:
package com.javacodegeeks.mockito; public class AccountManager { public static AccountSummary getSummary(AccountHolder accountHolder) { throw new UnsupportedOperationException(); } public static Transaction[] getTransactions(AccountHolder accountHolder) { throw new UnsupportedOperationException(); } }
Let’s also view the other POJOs that represents the account summary and the transaction.
AccountSummary:
package com.javacodegeeks.mockito; public class AccountSummary { private AccountHolder accountHolder; private long currentBalance; public AccountSummary(AccountHolder accountHolder, long currentBalance) { this.accountHolder = accountHolder; this.currentBalance = currentBalance; } public AccountHolder getAccountHolder() { return accountHolder; } public long getCurrentBalance() { return currentBalance; } }
Transaction:
package com.javacodegeeks.mockito; import java.util.Date; public class Transaction { private int serialNumber; private Date transactionDate; private String transactionType; private long amount; public Transaction(int serialNumber, Date transactionDate, String transactionType, long amount) { this.serialNumber = serialNumber; this.transactionDate = transactionDate; this.transactionType = transactionType; this.amount = amount; } public int getSerialNumber() { return serialNumber; } public Date getTransactionDate() { return transactionDate; } public String getTransactionType() { return transactionType; } public long getAmount() { return amount; } }
3. Mocking Static Method
Our AccountHolder.getMiniStatement()
calls static methods AccountManager.getSummary
and AccountManager.getTransactions
, and then combines the result into a Statement
object. Suppose we want to test the mini-statement functionality, for example, to make sure that the Statement
object is correctly formed. We can do this by mocking the static method AccountManager.getSummary
.
Before I start with the test case, let me first introduce you to couple of annotations:
- The test class is annotated with
@RunWith
annotation which is a type annotation and containsPowerMockRunner.class
. This tells JUnit to execute the test usingPowerMockRunner
. - Another important annotation is
@PrepareForTest(AccountManager.class)
which tells PowerMockto to prepareAccountManager
class for tests.
In our test case stubStaticMethodToGetMiniStatement
, we mock AccountManager.getSummary
to return us a known summary object and then we verify the statement object returned whether it contains the correct summary details.
We start mocking using PowerMockito.mockStatic(AccountManager.class)
which tells PowerMock that we want to mock all the static methods of the AccountManager
class. Next we will train AccountManager.getSummary
to return an AccountSummary
object.
PowerMockito.when(AccountManager.getSummary(accountHolder)).thenReturn(new AccountSummary(accountHolder, 9999));
AccountManagerStaticMethodExample:
package com.javacodegeeks.mockito; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) public class AccountManagerStaticMethodExample { private AccountHolder accountHolder = new AccountHolder("Joe", "123"); @PrepareForTest({ AccountManager.class }) @Test public void stubStaticMethodToGetMiniStatement() { long balance = 9999L; AccountSummary accountSummary = new AccountSummary(accountHolder, balance); p("Call mockStatic AccountManager.class to enable static mocking"); PowerMockito.mockStatic(AccountManager.class); p("Stub static method AccountManager.getSummary"); PowerMockito.when(AccountManager.getSummary(accountHolder)) .thenReturn(new AccountSummary(accountHolder, 9999)); // Run p("Let's get the mini-statement"); Statement statement = accountHolder.getMiniStatement(); p("Verify the account summary details are correct"); Assert.assertEquals(accountSummary.getAccountHolder(), statement.getAccountSummary().getAccountHolder()); Assert.assertEquals(accountSummary.getCurrentBalance(), statement.getAccountSummary().getCurrentBalance()); } private void p(String s) { System.out.println(s); } }
Output:
Call mockStatic AccountManager.class to enable static mocking Stub static method AccountManager.getSummary Let's get the mini-statement Verify the account summary details are correct
4. Verify Static Method Call
Since we have mocked AccountManager.getAccountSummary
, we know that the method was called so we will not verify it again. Right after the call to get summary, we make another static call to AccountManager
to get the account statements. We will improve our previous test case to verify that static method AccountManager.getTransactions
was called.
package com.javacodegeeks.mockito; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @RunWith(PowerMockRunner.class) public class AccountManagerStaticMethodExample { private AccountHolder accountHolder = new AccountHolder("Joe", "123"); @PrepareForTest({ AccountManager.class }) @Test public void stubStaticMethodToGetMiniStatement() { long balance = 9999L; AccountSummary accountSummary = new AccountSummary(accountHolder, balance); p("Call mockStatic AccountManager.class to enable static mocking"); PowerMockito.mockStatic(AccountManager.class); p("Stub static method AccountManager.getSummary"); PowerMockito.when(AccountManager.getSummary(accountHolder)) .thenReturn(new AccountSummary(accountHolder, 9999)); // Run p("Let's get the mini-statement"); Statement statement = accountHolder.getMiniStatement(); p("Verify the account summary details are correct"); Assert.assertEquals(accountSummary.getAccountHolder(), statement.getAccountSummary().getAccountHolder()); Assert.assertEquals(accountSummary.getCurrentBalance(), statement.getAccountSummary().getCurrentBalance()); p("Verify AccountManager.getTransactions was called"); PowerMockito.verifyStatic(); AccountManager.getTransactions(accountHolder); } private void p(String s) { System.out.println(s); } }
Note the highlighted statements. We first let PowerMock know that we will are going to verify static method by calling PowerMockito.verifyStatic()
. Then we actually have to invoke the static method. This is not considered as an actual method invocation but as a static method verification.
Output:
Call mockStatic AccountManager.class to enable static mocking Stub static method AccountManager.getSummary Let's get the mini-statement Verify the account summary details are correct Verify AccountManager.getTransactions was called
5. Download Source Code
This was an example about mocking static methods using PowerMockito.
You can download the full source code of this example here: powerMockitoStaticMethod.zip
very well explained, however i downloaded source project and ran in eclipse i got below error
com.javacodegeeks.mockito.AccountManagerStaticMethodExample#initializationError
Failed
6ms
Message:
java.lang.reflect.InvocationTargetException
Stack trace:
org.objenesis.ObjenesisException: java.lang.reflect.InvocationTargetException
could you help.
it is thrown while working with the reflection API and attempting to invoke a method that throws an underlying exception itself