Mockito

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:

1. Dependencies in pom.xml

Our dependencies consist of:

  1. junit
  2. mockito-core
  3. powermock-api-mockito
  4. 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:

  1. The test class is annotated with @RunWith annotation which is a type annotation and contains PowerMockRunner.class. This tells JUnit to execute the test using PowerMockRunner.
  2. Another important annotation is @PrepareForTest(AccountManager.class) which tells PowerMockto to prepare AccountManager 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.

Download
You can download the full source code of this example here: powerMockitoStaticMethod.zip

Ram Mokkapaty

Ram holds a master's degree in Machine Design from IT B.H.U. His expertise lies in test driven development and re-factoring. He is passionate about open source technologies and actively blogs on various java and open-source technologies like spring. He works as a principal Engineer in the logistics domain.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Mary
Mary
4 years ago

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.

karan
karan
4 years ago
Reply to  Mary

it is thrown while working with the reflection API and attempting to invoke a method that throws an underlying exception itself

Back to top button