The below test throws java.lang.IllegalStateException: no last call on a mock available
when I don't extend from the PowerMockTestCase.
The error disappears as soon as I extend from PowerMockTestCase. Why exactly is this happening?
import static org.junit.Assert.assertEquals;
import org.easymock.EasyMock;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.testng.PowerMockTestCase;
@PrepareForTest({ IdGenerator.class, ServiceRegistartor.class })
public class SnippetTest extends PowerMockTestCase{
@org.testng.annotations.Test
public void testRegisterService() throws Exception {
long expectedId = 42;
// We create a new instance of test class under test as usually.
ServiceRegistartor tested = new ServiceRegistartor();
// This is the way to tell PowerMock to mock all static methods of a
// given class
PowerMock.mockStatic(IdGenerator.class);
/*
* The static method call to IdGenerator.generateNewId() expectation.
* This is why we need PowerMock.
*/
EasyMock.expect(IdGenerator.generateNewId()).andReturn(expectedId).once();
// Note how we replay the class, not the instance!
PowerMock.replay(IdGenerator.class);
long actualId = tested.registerService(new Object());
// Note how we verify the class, not the instance!
PowerMock.verify(IdGenerator.class);
// Assert that the ID is correct
assertEquals(expectedId, actualId);
}
}
While using PowerMock for static mocking, there is a class level instrumentation happening to make your mocking work. PowerMockTestCase class has a code (method beforePowerMockTestClass()) to switch your regular class loader to powermock class loader which orchestrates mocking injection. Hence you need to extend this class for static mock to work.
You need to have the PowerMock class-loaders configured so that the static classes can be intercepted (defined using the @PrepareForTest
annotation).
You don't have to extend from PowerMockTestCase. For most cases you can also configure TestNG with a PowerMockObjectFactory instead:
@PrepareForTest({ IdGenerator.class, ServiceRegistartor.class })
public class SnippetTest {
@ObjectFactory
public IObjectFactory objectFactory() {
return new PowerMockObjectFactory();
}
@org.testng.annotations.Test
public void testRegisterService() throws Exception {
...
}
}
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