How do I mock an implementation class? - java

I have something like this:
public interface SomeInterface {
public String someMethod(String someArg1, String someArg2);
}
public class SomeInterfaceImpl {
#Override
public String someMethod(String someArg1, String someArg2) {
String response;
// a REST API call which fetches response (need to mock this)
return response;
}
}
public class SomeClass {
public int execute() {
int returnValue;
// some code
SomeInterface someInterface = new SomeInterfaceImpl();
String response = someInterface.someMethod("some1", "some2");
// some code
return returnValue;
}
}
I want to test the execute() method in SomeClass using JUnit. Since someMethod(String someArg1, String someArg2) calls a REST API, I want to mock someMethod to return some predefined response. But somehow, the real someMethod gets called instead of returning the predefined response. How do I make it work?
Here is what I have tried using Mockito and PowerMockito:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ SomeInterface.class, SomeInterfaceImpl.class, SomeClass.class })
public class SomeClassTest {
#Test
public void testExecute() {
String predefinedResponse = "Some predefined response";
int expectedReturnValue = 10;
SomeInterfaceImpl impl = PowerMockito.mock(SomeInterfaceImpl.class);
PowerMockito.whenNew(SomeInterfaceImpl.class).withAnyArguments().thenReturn(impl);
PowerMockito.when(impl.someMethod(Mockito.any(), Mockito.any())).thenReturn(predefinedResponse);
SomeClass someClass = new SomeClass();
int actualReturnValue = someClass.execute();
assertEquals(expectedReturnValue, actualReturnValue);
}
}

Here is an example of injecting dependencies without a framework:
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.when;
interface SomeInterface {
String someMethod(String someArg1, String someArg2);
}
class SomeInterfaceImpl implements SomeInterface {
#Override
public String someMethod(String someArg1, String someArg2) {
String response;
response = "the answer.";// a REST API call which fetches response (need to mock this)
return response;
}
}
class SomeClass {
private final SomeInterface someInterface;
SomeClass(final SomeInterface someInterface) {
this.someInterface = someInterface;
}
public SomeClass() {
this(new SomeInterfaceImpl());
}
public int execute() {
int returnValue;
// some code
String response = someInterface.someMethod("some1", "some2");
returnValue = 42; // some code
return returnValue;
}
}
#RunWith(MockitoJUnitRunner.class)
class SomeClassTest {
private static final String SOME_PREDEFINED_RESPONSE = "Some predefined response";
#Mock
private SomeInterface someInterface;
#InjectMocks
private SomeClass underTest;
#Before
public void setup() {
when(someInterface.someMethod(anyString(), anyString())).thenReturn(SOME_PREDEFINED_RESPONSE);
}
#Test
public void testExecute() {
int expectedReturnValue = 42;
int actualReturnValue = underTest.execute();
assertEquals(expectedReturnValue, actualReturnValue);
}
}

You don't have to do that.
You change your method under test to NOT call new directly.
Instead you use dependency injection for example.
Yes, this could be done with Powermock, but please believe me: doing so is the wrong approach!

This answer is very similar to answer posted by Andreas, the only difference being you can run this with #RunWith(SpringRunner.class) and it will avoid problems with bean instantiation and extra configuration. Avoid Powermocks and use it only when you need to mock static classes.
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.when;
interface SomeInterface {
String someMethod(String someArg1, String someArg2);
}
class SomeInterfaceImpl implements SomeInterface {
#Override
public String someMethod(String someArg1, String someArg2) {
String response;
response = "the answer.";// a REST API call which fetches response (need to mock this)
return response;
}
}
class SomeClass {
private final SomeInterface someInterface;
SomeClass(final SomeInterface someInterface) {
this.someInterface = someInterface;
}
public SomeClass() {
this(new SomeInterfaceImpl());
}
public int execute() {
int returnValue;
// some code
String response = someInterface.someMethod("some1", "some2");
returnValue = 42; // some code
return returnValue;
}
}
#RunWith(MockitoJUnitRunner.class)
class SomeClassTest {
private static final String SOME_PREDEFINED_RESPONSE = "Some predefined response";
#Mock
private SomeInterface someInterface;
#InjectMocks
private SomeClass underTest;
#Before
public void setup() {
when(someInterface.someMethod(anyString(), anyString())).thenReturn(SOME_PREDEFINED_RESPONSE);
}
#Test
public void testExecute() {
int expectedReturnValue = 42;
int actualReturnValue = underTest.execute();
assertEquals(expectedReturnValue, actualReturnValue);
}
}

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.

Spy an already initialized Java object Mockito

I am using the Mocktio library to write some test cases, since I have an elaborate inhertance structure, I have a few objects which are instantiated in the parent class, and I would like to mock one of its function call. Does Mockito library provide any way to spy on a already initialized object?
Also, the object is not directly instantiable.
Similar to the following -
public class A {
protected static MyObject a;
public static void someMethod() {
a = myObjectBuilder.createObj();
}
}
And another class B looks something similar to
class B extends A {
#BeforeClass
public static void setUpBeforeClass() {
someMethod();
}
#Test
public void mockTest() {
// now mock behavior of some method of MyObject a
// Missing line to spy object a.
Mockito.doReturn(false).when(a).xyz();
/* Now call some method that triggers a.xyz()
again, it is not a direct call,
there are multiple layer of abstraction
*/
}
}
Edit: I have tried the following and it does not work
MyObject mock_object = Mockito.spy(a);
Mockito.doReturn(false).when(mock_object).xyz();
Basically, don't do initialisation in BeforeClass, it runs only once but
you need to have new spy in each test, or you must "reinitialise" spy object
before each test.
Please examine this code:
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
import static org.assertj.core.api.Assertions.assertThat;
class MyObject{
public String cos;
public MyObject(String cos) {
this.cos = cos;
}
public boolean xyz() {
return true;
}
}
class A {
protected static MyObject a;
public void someMethod() {
a = new MyObject("cccc");
}
}
public class B extends A {
#Before
public void setUpBeforeTest() {
someMethod();
}
#Test
public void mockTest() {
MyObject mock_object = Mockito.spy(a);
Mockito.doReturn(false).when(mock_object).xyz();
assertThat(mock_object.xyz()).isFalse();
}
#Test
public void mockTest2() {
MyObject mock_object = Mockito.spy(a);
Mockito.doReturn(true).when(mock_object).xyz();
assertThat(mock_object.xyz()).isTrue();
}
}
If you want it your way, please change:
public void someMethod() {
a = myObjectBuilder.createObj();
}
into:
public static void someMethod() {
a = myObjectBuilder.createObj();
}
You can't call non static method from static initialiser #BeforeClass:
class A {
protected static MyObject a;
public static void someMethod() {
a = new MyObject("cccc");
}
}
public class B extends A {
#BeforeClass
public static void setUpBeforeClass() {
someMethod();
}
#Test
public void mockTest() {
MyObject mock_object = Mockito.spy(a);
Mockito.doReturn(false).when(mock_object).xyz();
assertThat(mock_object.xyz()).isFalse();
}
#Test
public void mockTest2() {
MyObject mock_object = Mockito.spy(a);
// Here we replace original object with our spy
A.a = mock_object;
Mockito.doReturn(false).when(mock_object).xyz();
assertThat(a.xyz()).isFalse();
}
}
Another example (in this case we replace object a with mock (spy is not needed):
class MyObject{
public String cos;
public MyObject(String cos) {
this.cos = cos;
}
public boolean xyz() {
return true;
}
}
class A {
protected MyObject a;
public A() {
a = new MyObject("ggggg");
}
public String doSomethingWithA(){
if(a.xyz()){
return a.cos;
}
else{
return "aaaa";
}
}
}
#RunWith(MockitoJUnitRunner.class)
public class B {
#Mock
MyObject mock_object;
#InjectMocks
A systemUnderTest = new A();
#Test
public void mockTest1() {
Mockito.doReturn(false).when(mock_object).xyz();
assertThat(systemUnderTest.doSomethingWithA()).isEqualTo("aaaa");
}
#Test
public void mockTest2() {
Mockito.doReturn(true).when(mock_object).xyz();
assertThat(systemUnderTest.doSomethingWithA()).isNull();
}
}

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();
});

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