public class ClassWithPrivateStaticMethods {
private static String getParam(String paramName) {
String result = "";
...
...
return result;
}
private static String getDetail(String contextName) {
String result = "";
String temp = getParam(tempParamName);
...
return result;
}
}
PowerMockito.mockStatic(ClassWithPrivateStaticMethods.class);
PowerMockito.when(ClassWithPrivateStaticMethods.class, "getParam", Mockito.anyString()).thenReturn("dummy");
Problem
PowerMockito.mockStatic() actually mocks all the static method in the class.So if you have the circumstance where you want to mock one static method, but you want other method to run normally, then this method will not work. Because the other method will also be mocked.
PowerMockito.mockStatic(ClassWithPrivateStaticMethods.class)
PowerMockito.when(ClassWithPrivateStaticMethods.class, "getParam", Mockito.anyString()).thenReturn("dummy");
String result = Whitebox.invokeMethod(ClassWithPrivateStaticMethods.class, "getDetail", Mockito.anyString());
Solution - Partial Mocking
We can solve this by mocking individual static methods by following way:
PowerMockito.spy(ClassWithPrivateStaticMethods.class);
PowerMockito.doReturn("dummy").when(ClassWithPrivateStaticMethods.class, "getParam", Mockito.anyString())
String finalResult = Whitebox.invokeMethod(ClassWithPrivateStaticMethods.class, "getDetail", Mockito.anyString());
Complete Code Demonstration
Following is a complete code demonstration.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* File: StaticMethodsTest.java | |
* Created: 2018-05-03 | |
* Author: Sabbir Manandhar | |
* | |
* Copyright (c) 2018 Hogwarts. | |
*/ | |
package com.worldlingo; | |
import junit.framework.Assert; | |
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; | |
/** | |
* JUnit test cases using PowerMockito for the Static Methods in a Class | |
* | |
* @author Sabbir Manandhar | |
* @version 1.0 | |
*/ | |
@RunWith(PowerMockRunner.class) | |
@PrepareForTest({TestClass.class}) | |
public class StaticMethodsTest { | |
/** | |
* PowerMockito.mockStatic(); mocks all the static methods in a class | |
* So even you explicitly define mocked return for the static method, | |
* execution of the method in the test will still be mocked and won't execute | |
* its actual code. Instead it will return null (or appropriate value) if it | |
* has return value. | |
* | |
* @throws Exception | |
*/ | |
@Test | |
public void test() throws Exception { | |
PowerMockito.mockStatic(TestClass.class); | |
PowerMockito.doReturn("TOM").when(TestClass.class, "toUpperCase", Mockito.anyString()); | |
String result1 = TestClass.toUpperCase("I am the king"); | |
String result2 = TestClass.toLowerCase("I am the king"); | |
String result3 = TestClass.alterWords("I am the king"); | |
Assert.assertEquals("TOM", result1); | |
Assert.assertNull(result2); | |
Assert.assertNull(result3); | |
} // test | |
//----------------------------------------------------------------------------------------------- | |
/** | |
* Similar to first test method | |
* All static methods will be mocked | |
* Here return value for each static methods are defined, and results are as expected | |
* | |
* @throws Exception | |
*/ | |
@Test | |
public void test2() throws Exception { | |
PowerMockito.mockStatic(TestClass.class); | |
PowerMockito.doReturn("TOM").when(TestClass.class, "toUpperCase", Mockito.anyString()); | |
PowerMockito.doReturn("marvolo").when(TestClass.class, "toLowerCase", Mockito.anyString()); | |
PowerMockito.doReturn("VoLdEmOrT").when(TestClass.class, "alterWords", Mockito.anyString()); | |
String result1 = TestClass.toUpperCase("I am the king"); | |
String result2 = TestClass.toLowerCase("I am the king"); | |
String result3 = TestClass.alterWords("I am the king"); | |
Assert.assertEquals("TOM", result1); | |
Assert.assertEquals("marvolo", result2); | |
Assert.assertEquals("VoLdEmOrT", result3); | |
} // test2 | |
//------------------------------------------------------------------------------------------------ | |
/** | |
* Mock individual Static method | |
* Here TestClass.toUpperCase() and TestClass.toLowerCase() are mocked | |
* but TestClass.alterWords() is not | |
* So TestClass.alterWords() will actually execute the original code which | |
* in turn invokes the methods toUpperCase() and toLowerCase(). Since these | |
* are mocked, mocked results will be returned. | |
* | |
* @throws Exception | |
*/ | |
@Test | |
public void test3() throws Exception { | |
PowerMockito.spy(TestClass.class); | |
PowerMockito.doReturn("TOM").when(TestClass.class, "toUpperCase", Mockito.anyString()); | |
PowerMockito.doReturn("marvolo").when(TestClass.class, "toLowerCase", Mockito.anyString()); | |
String result1 = TestClass.toUpperCase("I am the king"); | |
String result2 = TestClass.toLowerCase("I am the king"); | |
String result3 = TestClass.alterWords("I am the king"); | |
Assert.assertEquals("TOM", result1); | |
Assert.assertEquals("marvolo", result2); | |
Assert.assertEquals("TOM marvolo TOM marvolo ", result3); | |
} // test3 | |
} // StaticMethodsTest | |
//----------------------------------------------------------------------------------------- | |
/** | |
* Test class with Static Methods | |
*/ | |
class TestClass { | |
public static String toUpperCase(String input) { | |
return input.toUpperCase(); | |
} // toUpperCase | |
//--------------------------------------------------------------------------------------- | |
public static String toLowerCase(String input) { | |
return input.toLowerCase(); | |
} // toLowerCase | |
//--------------------------------------------------------------------------------------- | |
public static String alterWords(String input) { | |
String[] comps = input.split(" "); | |
StringBuilder sb = new StringBuilder(); | |
boolean alt = true; | |
for (String comp : comps) { | |
if (alt) { | |
sb.append(toUpperCase(comp)).append(" "); | |
} else { | |
sb.append(toLowerCase(comp)).append(" "); | |
} | |
alt = !alt; | |
} | |
return sb.toString(); | |
} // alterWords | |
//---------------------------------------------------------------------------------------- | |
} // TestClass |
No comments:
Post a Comment