PowerMockito: mocking private method and get a value without accessing it - java

I'm writing java unit test for a legacy code and I'm new to this area as well. I have to test following scenario (write unit test case for the testableMethod()). So, without executing code inside the getMode() method, I want to get a value for the mode variable.
Class A{
public boolean testableMethod()
{
//code
......
int mode = getMode();
......
//do something with mode
return X;
}
private int getMode()
{
return ComplexCalls(ComplexMethodCalls(), more());
}
}
I've tried to do it using PowerMockito without getting success. It is possible to mock these kind of scenario with PowerMockito?.

You can with a PowerMockito spy:
public class A {
public boolean testableMethod() {
return getMode() == 1;
}
private int getMode() {
return 5;
}
}
import static org.junit.Assert.assertTrue;
import static org.powermock.api.mockito.PowerMockito.doReturn;
import static org.powermock.api.mockito.PowerMockito.spy;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(A.class)
public class ATest {
#Test
public void testableMethod_should_do_this() throws Exception {
A a = spy(new A());
doReturn(1).when(a, "getMode");
assertTrue(a.testableMethod());
}
}
See all this full example of partial mocking of a private method

Related

Unable to override static final variable of a final class using PowerMock

I'm trying to use PowerMock Whitebox setInternalState api to override a static final variable of a final class. But it doesn't seems to be working. Please see sample code below:
A final class with static final variable:
public final class BuildConfig {
public static final String BUILD_TYPE = "debug";
}
A helper class to return the above variable:
public class BuildConfigHelperClass {
public String getBuildType() {
return BuildConfig.BUILD_TYPE;
}
}
Test class
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import static org.junit.Assert.*;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
#RunWith(PowerMockRunner.class)
#SuppressStaticInitializationFor("BuildConfig")
#PrepareForTest({BuildConfigHelperClassTest.class, BuildConfigHelperClass.class, BuildConfig.class})
public class BuildConfigHelperClassTest {
private BuildConfigHelperClass subject;
#Before
public void setUp() {
subject = new BuildConfigHelperClass();
}
#Test
public void shouldReturnDebugBuildType() {
assertEquals("debug", subject.getBuildType());
}
#Test
public void shouldReturnProductionBuildType() {
mockStatic(BuildConfig.class);
Whitebox.setInternalState(BuildConfig.class, "BUILD_TYPE", "production");
assertEquals("production", subject.getBuildType());
}
}
In above test class, for second test subject.getBuildType() method should return "production" as I am overriding it through Whitebox, but it always fails because of return value i.e. "debug".
Can anyone please guide me on what I'm missing.
The compiler is optimizing the code, where this:
public class BuildConfigHelperClass {
public String getBuildType() {
return BuildConfig.BUILD_TYPE;
}
}
is essentially compiled to:
public class BuildConfigHelperClass {
public String getBuildType() {
return "debug";
}
}
so the unit test is running against compiled code which has no reference to BuildConfig.
Instead of referencing BUILD_TYPE directly, try adding a static getter:
public final class BuildConfig {
private static final String BUILD_TYPE = "debug";
public static final String getBuildType() {
return BUILD_TYPE;
}
}
Then the static method can be mocked:
#Test
public void shouldReturnProductionBuildType() {
mockStatic(BuildConfig.class);
// Whitebox.setInternalState(BuildConfig.class, "BUILD_TYPE", "production");
PowerMockito.when(BuildConfig.getBuildType()).thenReturn("production");
assertEquals("production", subject.getBuildType());
}
This test works on my local, although other compilers might still be able to optimize it away and break the test.

How to mock only one static method and test the other

#Mocked Provider provider;
public static class Provider {
public static List<Integer> getStaticList() {
return new ArrayList<>();
}
public static List<Integer> test() {
return getStaticList();
}
}
#Test
public void testStatic() {
ArrayList<Object> list = new ArrayList<>();
list.add(1);
new Expectations() {
{
Provider.getStaticList();
result = list;
}
};
assertThat(Provider.test(), JUnitMatchers.hasItem(1));
}
I want to mock (with JMockit) one static method that is called within another one. How can I do that? The above test fails. The real Provider.test method is never called.
The code below changes the behaviour of doSomething static method only, without affecting other static methods.
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import java.util.HashMap;
import java.util.Map;
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)
#PrepareForTest({Foo.class})
public class Snipets {
#Test
public void hoge() throws Exception {
PowerMockito.spy(Foo.class);
PowerMockito.when(Foo.class, "doSomething").thenReturn("dummy");
String actual = Foo.doSomething();
assertEquals("dummy", actual);
}
}
Foo.java
public class Foo {
public static String doSomething() {
return "foo";
}
}
Source: https://gist.github.com/mid0111/8859159
You can use partial mocking:
#Test
public void testStatic() {
new Expectations(Provider.class) {{ Provider.getStaticList(); result = 1; }};
List<Integer> test = Provider.test();
assertTrue(test.contains(1));
}
(With no "#Mocked Provider" field for the test above.)
I used a very simple method of writing a conditional answer like this:
PowerMockito.mockStatic(<MyMockedClass>.class, invocation -> {
if (invocation.getMethod().getName().equals("<methodToMockName>")) {
return <mockedValue>;
}
return invocation.callRealMethod();
});

How can I suppress private method invocation in constructor?

I have a very very simple class which has a private method. The question is how to suppress this method invocation?
Here is my code:
public class Example {
private int value;
public Example(int value) {
this.value = value;
method();
}
private void method() {
throw new RuntimeException();
}
public int getValue() {
return value;
}
}
And code of test (attempt at least):
public void test() throws Exception {
PowerMockito.doNothing().when(Example.class, "method");
final int EXPECTED_VALUE = 1;
Example example = new Example(EXPECTED_VALUE);
int RETRIEVED_VALUE = example.getValue();
assertEquals(RETRIEVED_VALUE, EXPECTED_VALUE);
verifyPrivate(Example.class, times(1)).invoke("method");
}
UPD
For me is important to comply with these two terms:
PowerMockito.doNothing().when(Example.class, "method");
PowerMockito.verifyPrivate(Example.class, times(1)).invoke("method");
Since you can't modify the code under test. I think there isn't a perfect solution. You need to partially mock the Example instance.
List list = new LinkedList();
List spy = spy(list);
//You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
but you can't do this since you have to instantiate your object at first.
So i propose the following workaround composed of two tests. The first test remove the private method from the class, instantiate the Example and verify that the Example is correctly initialized.
The second test instantiate the Example and verify that a RuntimeException (the private method side effect).
import static org.junit.Assert.assertEquals;
import static org.powermock.api.support.membermodification.MemberMatcher.method;
import static org.powermock.api.support.membermodification.MemberModifier.suppress;
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)
#PrepareForTest(Example.class)
public class ExampleTest {
#Test
public void constructor_should_initialize_the_v2alue() throws Exception {
suppress(method(Example.class, "method"));
final int EXPECTED_VALUE = 1;
Example example = PowerMockito.spy(new Example(EXPECTED_VALUE));
int RETRIEVED_VALUE = example.getValue();
assertEquals(RETRIEVED_VALUE, EXPECTED_VALUE);
}
#Test(expected=RuntimeException.class)
public void constructor_should_invoke_the_private_method() throws Exception {
new Example(1);
}
}

Java JUnit framework #BeforeClass and (Power)Mockito for a static method [duplicate]

I'm writing unit tests using PowerMock, mocking behaviour of some util classes. Defining behaviour once for test class (by #BeforeClass annotation) causes:
first test invocation to return mocked value
second test invocation to return real method return value
Sample code:
import org.junit.Assert;
import org.junit.BeforeClass;
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)
#PrepareForTest( {A.class, B.class})
public class TestMockedMethods {
private static B b;
#BeforeClass
public static void setUp() {
PowerMockito.mockStatic(A.class);
PowerMockito.when(A.getVal()).thenReturn("X");
b = PowerMockito.mock(B.class);
PowerMockito.when(b.getVal()).thenReturn("Y");
}
#Test
public void test1() { // PASS
Assert.assertEquals("X", A.getVal());
Assert.assertEquals("Y", b.getVal());
}
#Test
public void test2() { // FAIL
Assert.assertEquals("X", A.getVal()); // actual="A"
Assert.assertEquals("Y", b.getVal()); // actual="B"
}
}
class A {
static String getVal() {
return "A";
}
}
class B {
String getVal() {
return "B";
}
}
Any ideas why second test is failing?
The method PowerMockito.mockStatic(...) invokes MockCreator.mock(...). This method regsiters a Runnable that will be executed after each test :
MockRepository.addAfterMethodRunner(new MockitoStateCleaner());
This runnable cleans the internal state of Mockito :
private static class MockitoStateCleaner implements Runnable {
public void run() {
clearMockProgress();
clearConfiguration();
}
private void clearMockProgress() {
clearThreadLocalIn(ThreadSafeMockingProgress.class);
}
private void clearConfiguration() {
clearThreadLocalIn(GlobalConfiguration.class);
}
private void clearThreadLocalIn(Class<?> cls) {
Whitebox.getInternalState(cls, ThreadLocal.class).set(null);
final Class<?> clazz = ClassLoaderUtil.loadClass(cls, ClassLoader.getSystemClassLoader());
Whitebox.getInternalState(clazz, ThreadLocal.class).set(null);
}
}
So you should execute your setUp before each test.
#Before
public void setUp() {
PowerMockito.mockStatic(A.class);
PowerMockito.when(A.getVal()).thenReturn("X");
b = PowerMockito.mock(B.class);
PowerMockito.when(b.getVal()).thenReturn("Y");
}

Mocking behaviour resets after each test with PowerMock

I'm writing unit tests using PowerMock, mocking behaviour of some util classes. Defining behaviour once for test class (by #BeforeClass annotation) causes:
first test invocation to return mocked value
second test invocation to return real method return value
Sample code:
import org.junit.Assert;
import org.junit.BeforeClass;
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)
#PrepareForTest( {A.class, B.class})
public class TestMockedMethods {
private static B b;
#BeforeClass
public static void setUp() {
PowerMockito.mockStatic(A.class);
PowerMockito.when(A.getVal()).thenReturn("X");
b = PowerMockito.mock(B.class);
PowerMockito.when(b.getVal()).thenReturn("Y");
}
#Test
public void test1() { // PASS
Assert.assertEquals("X", A.getVal());
Assert.assertEquals("Y", b.getVal());
}
#Test
public void test2() { // FAIL
Assert.assertEquals("X", A.getVal()); // actual="A"
Assert.assertEquals("Y", b.getVal()); // actual="B"
}
}
class A {
static String getVal() {
return "A";
}
}
class B {
String getVal() {
return "B";
}
}
Any ideas why second test is failing?
The method PowerMockito.mockStatic(...) invokes MockCreator.mock(...). This method regsiters a Runnable that will be executed after each test :
MockRepository.addAfterMethodRunner(new MockitoStateCleaner());
This runnable cleans the internal state of Mockito :
private static class MockitoStateCleaner implements Runnable {
public void run() {
clearMockProgress();
clearConfiguration();
}
private void clearMockProgress() {
clearThreadLocalIn(ThreadSafeMockingProgress.class);
}
private void clearConfiguration() {
clearThreadLocalIn(GlobalConfiguration.class);
}
private void clearThreadLocalIn(Class<?> cls) {
Whitebox.getInternalState(cls, ThreadLocal.class).set(null);
final Class<?> clazz = ClassLoaderUtil.loadClass(cls, ClassLoader.getSystemClassLoader());
Whitebox.getInternalState(clazz, ThreadLocal.class).set(null);
}
}
So you should execute your setUp before each test.
#Before
public void setUp() {
PowerMockito.mockStatic(A.class);
PowerMockito.when(A.getVal()).thenReturn("X");
b = PowerMockito.mock(B.class);
PowerMockito.when(b.getVal()).thenReturn("Y");
}

Categories

Resources