5

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

}
Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
Ajay
  • 2,976
  • 2
  • 28
  • 35
  • on which line does it give this exception?can you put the exception trace, it might be of some help – Vihar Feb 23 '15 at 11:27
  • Sorry @vihar I dont have this setup any more. But as far I remember it is thrown from the line PowerMock.replay(IdGenerator.class); – Ajay Feb 24 '15 at 07:44
  • ok ,either close this question or answer it yourself – Vihar Feb 24 '15 at 08:34

2 Answers2

4

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.

Prabakar K
  • 138
  • 2
  • 9
1

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 {
      ...
   }
}
tony.ganchev
  • 596
  • 4
  • 14