I am trying to mock a private method using PowerMockito.
Sample code is given below.
Ideally m2() should be returning "from spy method".
Not sure what could be missing.
Please clarify.
Sample.java
import java.io.IOException;
public class Sample {
public void m1(String input) throws IOException {
System.out.println("Sample.m1() BEGIN");
String r = m2(input);
System.out.println("Sample.m1() END--> " + r);
}
private String m2(String s) {
System.out.println("Sample.m2()" + s);
return "From m2 method";
}
}
SampleTest.java
import static org.mockito.Matchers.anyString;
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({ Sample.class })
public class SampleTest {
#Test
public void testM1() throws Exception {
Sample spy = PowerMockito.spy(new Sample());
PowerMockito.doReturn("from spy method").when(spy, "m2", anyString());
Sample sample = new Sample();
sample.m1("Hi m1!!!");
}
}
Output
Sample.m1() BEGIN
Sample.m2()Hi m1!!!
Sample.m1() END--> From m2 method
I needed to call m1() on spy instance instead of sample instance.
Thanks to Giacomo Alzetta for the suggestion.
Modified code:
#Test
public void testM1() throws Exception {
Sample spy = PowerMockito.spy(new Sample());
PowerMockito.doReturn("from spy method").when(spy, "m2", anyString());
spy.m1("Hi m1!!!");
}
Related
I read at least 20 posts but still couldn't find the answer. So, posting this question. May be it is answered in some other post, which I couldn't find.
class OuterService {
InnerService innerService;
#Autowired
public void setInnerService(InnerService innerService){
this.innerService = innerService;
}
public void method() {
List<C> listOfC = new ArrayList<C>();
C c = new C();
c.setUserProfiles(someObject);
c = innerService.invokeMethod(String str1,Map map,
String str2, Object obj1, String str3, String str4,
C c, String str5);
c.setCreatedDate(some String value); // Here c comes null while executing jUnits.
listOfC.add(c);
}
}
Here is my Test class:
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import com.pogo.service.DeviceRegistrationService;
#SuppressFBWarnings("RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT")
#SpringBootTest
#RunWith(MockitoJUnitRunner.class)
class ClassOuterServiceTest {
#InjectMocks
OuterService outerService;
#Mock
InnerService innerService;
#Mock C c;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
outerService.setInnerService(innerService);
}
#Test
public void methodTest() {
when(innerService.invokeMethod(Mockito.anyString(),
Mockito.any(Map.class), Mockito.anyString(),Mockito.anyString(),
Mockito.any(PersonSessionToken.class), Mockito.anyString(),Mockito.anyString(), Mockito.anyString(),
Mockito.any(RequestHeader.class),Mockito.any(C.class),
Mockito.anyString() )).thenReturn(c);
doNothing().when(c).invokeCMethod();
outerService.method();
}
}
But I get null inside object c in OuterService.java. Also if I use Matchers.any() or Matchers.anyString() in invokeMethod() then , it shows Matchers exception.
What is the appropriate solution?
You don't need to create the object for OuterService use #InjectMocks annotation and when you use method stubbing use mock objects only. In your program you are creating object for c. Instead of creating object just use #Mock annotation.
When you using Mockito.any() mention the class inside parenthesis. Mockito.any(C.class) like this.
Don't use PowerMockRunner unless you are testing static or final classes.
#SpringBootTest
#RunWith(MockitoJUnitRunner.class)
public class ClassOuterServiceTestC {
#Mock
public InnerService innerService;
#InjectMocks
public OuterService outerService;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void methodTest() {
C obj = mock(C.class);
when(innerService.invokeMethod(anyString(), anyMap(), anyString(), any(), anyString(), anyString(), any(TestC.class), anyString()))
.thenReturn(obj);
doNothing().when(obj).setUserProfiles(any(Object.class));
doNothing().when(obj).setCreatedDate(anyString());
outerService.method();
}
}
I want to test the following example code:
public class Example {
...
public void doStuff() {
...
Lift lift = new Lift();
lift.call(5);
...
}
...
}
How can I 'intercept' lift.call(5)?
Generally I would use when(lift.call(anyInt()).thenReturn(...), but I have no reference to the Lift object.
You can't do it with mockito alone. The cleanest solution is to refactor your code so you can have access to it. However if that's not an option then "power mockito" is what you want. Grab "powermock-api-mockito"+"powermock-module-junit4" and then something like this will do the trick:
import static org.mockito.Mockito.verify;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
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 {
private Example testSubject;
#Mock
private Lift lift;
#Test
public void testDoStuff() throws Exception {
testSubject.doStuff();
verify(lift).call(5);
}
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
PowerMockito.whenNew(Lift.class).withNoArguments().thenReturn(lift);
testSubject = new Example();
}
}
Can you modify the Example class? If yes, the simplest way would be to extract the Lift dependency and provide it via constructor. Like this:
public class Example {
private final Lift lift;
public Example(Lift lift) {
this.lift = lift;
}
public void doStuff() {
this.lift.call(5);
}
}
Then you can stub lift as you want since now you have access to the instance.
I have a final class as below
public class firstclass{
private String firstmethod(){
return new secondclass("params").somemethod();
}
}
public final class secondclass{
secondclass(String params){
//some code
}
public String somemethod(){
// some code
return somevariable";
}
}
I have to here test first class so I have mocked this as below
secondclass classMock = PowerMockito.mock(secondclass .class);
PowerMockito.whenNew(secondclass .class).withAnyArguments().thenReturn(classMock);
Mockito.doReturn("test").when(classMock).somemethod();
But it is not mocking as I expected can anyone help me?
The method firstclass.firstmethod() is private method. So try to test this method through public method in which it is getting called.
You can mock SecondClass and its final method using #RunWith(PowerMockRunner.class) and #PrepareForTest(SecondClass.class) annotations.
Please see below the working code:
import org.junit.After;
import org.junit.Before;
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;
#RunWith(PowerMockRunner.class)
#PrepareForTest(SecondClass.class)
public class FirstClassTest{
#Before
public void init() {
}
#After
public void clear() {
}
#Test
public void testfirstmethod() throws Exception{
SecondClass classMock = PowerMockito.mock(SecondClass.class);
PowerMockito.whenNew(SecondClass.class).withAnyArguments().thenReturn(classMock);
Mockito.doReturn("test").when(classMock).somemethod();
new FirstClass().firstmethod();
}
}
Libraries used:
The code is posted at link
now when i am trying to write the junit for
first case i am getting the error
"need to replay the class B ".
but same junit is working for the second case.
my junit is
#RunWith(PowerMockRunner.class)
public class TestClass {
#Test
public void testDoSomeThing() {
B b = createMock(B.class)
expectNew(b.CallMe()).andReturns(xxx)
A a=new A();
replayAll();
a.doSomething();
verifyAll();
}
}
Here's a solution using EasyMock with PowerMock :
TestClass.java
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest({ A.class, B.class })
public class TestClass {
#Test
public void testDoSomeThing() throws Exception {
/* Setup */
B bMock = PowerMock.createMock(B.class);
/* Mocks */
PowerMock.expectNew(B.class).andReturn(bMock).atLeastOnce();
bMock.callMe();
/* Activate */
PowerMock.replayAll();
/* Test */
A cut = new A();
cut.doSomething();
/* Asserts */
PowerMock.verifyAll();
}
}
A.java
public class A {
B b = new B();
public void doSomething() {
b.callMe();
}
}
B.java
public class B {
public void callMe() {
}
}
You forgot to add
#PrepareForTest({A.class, B.class})
This annotation must have the classes you are mocking and the classes that will use these mocks.
MyClass.java:
package test;
public final class MyClass {
public MyClass() { }
public Package returnPackage() {
return MyClass.class.getPackage();
}
}
TestClass.java:
package test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.powermock.api.mockito.PowerMockito.*;
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
public class TestClass {
#Test
public void test() throws Exception {
System.out.println(new MyClass().returnPackage());
mockStatic(MyClass.class);
System.out.println(new MyClass().returnPackage());
}
}
However, this results in:
package test
null
Any MyClass.class method call returns null after PowerMockito.mockStatic(Class). Is there any way to prevent this?
Workaround: I can use the EasyMock-API to set up the static mocks without PowerMockito.mockStatic().