I have a simple case to illustrate a much more complicated one (oh Legacy Code, do I love you, shall minstrels sing marvellous songs in thy name).
Picture a set of class as the following :
package org.osef.test;
public final class A {
private static A instance;
public static String status;
private A() {
initPaths();
}
public static A getInstance(){
if(instance==null){
instance = new A();
}
return instance;
}
private void initPaths() {
A.status = "I have been in the method !";
}
public String doStuff() {
return "stuff done ...";
}
}
package org.osef.test;
public class B {
public String doBdo() {
A instance = A.getInstance();
return instance.doStuff();
}
}
package org.osef.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.easymock.EasyMock;
import org.junit.Before;
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;
import org.powermock.reflect.Whitebox;
@RunWith(PowerMockRunner.class)
@PrepareForTest({ A.class })
public class BTest {
@Before
public void setUp() {
PowerMock.replace(PowerMock.method(A.class, "getInstance")).with(PowerMock.method(BTest.class, "giveOutInstance"));
A a = A.getInstance();
EasyMock.expect(a.doStuff()).andReturn("lol");
EasyMock.replay(a);
}
@Test
public void testDoBdo() {
B b = new B();
assertEquals("lol", b.doBdo());
assertNull(A.status);
}
public static A giveOutInstance(){
return Whitebox.newInstance(A.class);
}
}
package org.osef.test;
//[imports ommited here but are the same that those of the previous example]
@RunWith(PowerMockRunner.class)
@PrepareForTest({ A.class })
public class BTest {
@Before
public void setUp() {
PowerMock.mockStatic(A.class);
A a = Whitebox.newInstance(A.class);
EasyMock.expect(A.getInstance()).andReturn(a);
PowerMock.replay(A.class);
EasyMock.expect(a.doStuff()).andReturn("lol");
EasyMock.replay(a);
}
@Test
public void testDoBdo() {
B b = new B();
assertEquals("lol", b.doBdo());
assertNull(A.status);
}
}
But in all cases I get :
java.lang.IllegalStateException: no last call on a mock available at org.easymock.EasyMock.getControlForLastCall(EasyMock.java:560) at org.easymock.EasyMock.expect(EasyMock.java:538) at org.osef.test.BTest.setUp(BTest.java:25) ...
Any idea how to do what I want to do effectively ?
I think your issue is that you're not replaying the classes, you're only replaying the mock instance of A in each test.
PowerMock.replayAll()
is your friend here. It will force the classes you've got expectations on to be in replay mode, then your mock instance can be returned by the invocation of the static method.
Here is a sample test I produced for your example:
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.easymock.EasyMock;
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)
public class BTest{
@Test
public void thatCallingClassMakesExpectedCalls() {
final A mockA = PowerMock.createMock(A.class);
EasyMock.expect(mockA.doStuff()).andReturn("lol").anyTimes();
PowerMock.mockStatic(A.class);
EasyMock.expect(A.getInstance()).andReturn(mockA).anyTimes();
PowerMock.replayAll(mockA);
final B callingClass = new B();
final String doBdo = callingClass.doBdo();
assertThat(doBdo, is("lol"));
EasyMock.verify(mockA);
PowerMock.verifyAll();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With