2

To mock a static method powermock giving an exception while expect().

@Test
public void testRegistrarService()
{
   mockStatic(IdGenerator.class);
   expect(IdGenerator.generateNewId()).andReturn(42L);
   long actualId=serTestObj.registerService();
   replay(IdGenerator.class);
   verify(IdGenerator.class);
   assertEquals(42L,actualId);
 }


public class ServiceRegistrator
{
public long registerService()
{
    long id = IdGenerator.generateNewId();
    return id;
 }
}

public class IdGenerator
{
  public static long generateNewId()
  {
    return System.currentTimeMillis();
  }
}

Exception is:

java.lang.IllegalStateException: no last call on a mock available
at org.easymock.EasyMock.getControlForLastCall(EasyMock.java:521)
at org.easymock.EasyMock.expect(EasyMock.java:499)
at  home.powermock.testServiceRegistrator.testRegistrarService(testServiceRegistrator.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at com.intellij.rt.execution.junit2.JUnitStarter.main(JUnitStarter.java:31)

how to mock staic method,while m using powerMock i'm using intelliJ idea,how to resolve that exception.

4

4 回答 4

6

Your code is missing the annotation

@PrepareForTest(IdGenerator.class)
于 2013-06-25T10:56:04.390 回答
4

就我而言,我的测试类中缺少以下方法

   @ObjectFactory
   /**
    * Configure TestNG to use the PowerMock object factory.
    */
   public IObjectFactory getObjectFactory() {
      return new org.powermock.modules.testng.PowerMockObjectFactory();
   }

一旦我添加它,我就摆脱了“没有最后一次调用可用的模拟”错误。

于 2013-09-12T14:44:08.283 回答
3

您需要在实际调用该方法之前进行重播。

编辑:我认为部分问题可能是由于您的进口引起的。尽量不要导入 static powermock 和 static easymock (我发现我经常把自己弄糊涂,忘记了我需要在哪一个上调用 replay)。

尝试运行以下代码。如果它没有正确运行,那么可能是因为您拥有的特定版本的 PowerMock/EasyMock/Junit 存在问题。

测试类:

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 static org.easymock.EasyMock.*;

import static org.junit.Assert.*;
@RunWith(PowerMockRunner.class)
@PrepareForTest(IdGenerator.class)
public class TestClass {

@Test
public void testRegistrarService()
{
    ServiceRegistrator serTestObj = new ServiceRegistrator();

    PowerMock.mockStatic(IdGenerator.class);
    expect(IdGenerator.generateNewId()).andReturn(42L);
    PowerMock.replay(IdGenerator.class);
    long actualId=serTestObj.registerService();
    PowerMock.verify(IdGenerator.class);
    assertEquals(42L,actualId);
 }
}

标识符生成器:

public class IdGenerator {
     public static long generateNewId()
      {
        return System.currentTimeMillis();
      }
}

服务注册者:

public class ServiceRegistrator {
    public long registerService()
    {
        long id = IdGenerator.generateNewId();
        return id;
     }
}
于 2013-06-25T23:42:20.873 回答
3

这个问题已经存在了很长时间,但我会尝试给它一个回答来解释我为解决这个问题所做的工作。

首先,您必须使用这两个注释:

@RunWith(PowerMockRunner.class)

这个注解让当前的测试类知道用什么来运行他的测试,这很有用,因为我们可以使用 PowerMockRunner 而不是 JUnitRunner

@PrepareForTest(IdGenerator.class)

此注解用于准备要在测试中使用的类“IdGenerator”,准备意味着我们将能够像对公共方法一样模拟静态方法

添加这两个注释后,我们必须确保我们使用的是 PowerMock 提供的正确包:

1)动力模拟:

  • 导入:导入 org.powermock.api.easymock.PowerMock;
  • 使用:我们将使用 PowerMock 来模拟(而不仅仅是)我们的静态方法,代码如下

    PowerMock.mockStatic(IdGenerator.class);

2)EasyMock:

  • 导入:导入 org.easymock.EasyMock;
  • 使用:我们将使用 EasyMock 来伪造我们的对象以通过我们的静态方法返回:

    EasyMock.expect(IdGenerator.generateNewId()).andReturn(42L);

这是关于使用 PowerMock 和 EasyMock 的两个示例,在这里我将尝试解释代码及其作用:

mockStatic(IdGenerator.class);
//We mock our IdGenerator class which have the static object

expect(IdGenerator.generateNewId()).andReturn(42L);
//We fake our method return object, when we'll call generateNewId()
//method it will return 42L
//With expecting we "record" our this method and we prepare it to be     
//changed (it will return our decided value)

replay(IdGenerator.class);
//We go to perform our methods "registered" with the expect method
//inside the IdGenerator class, in this case with replay we just apply
//the changes of the expect to the method generateNewId()

long actualId = serTestObj.registerService();
//We create our object (which inside have a non static method that
//use generateNewId() static method)

verify(IdGenerator.class);
//We verify that the our faked method have been called

assertEquals(42L,actualId);
//We see if the two values are matching

请注意,因为在创建将调用静态伪造方法的新对象(本示例中为实际 ID)之前必须使用重播。

还要多注意您要导入的内容,以免分散我的注意力

PowerMockito.mockStatic(className.class);
//from import org.powermock.api.mockito.PowerMockito;

代替

PowerMock.mockStatic(className.class);
//from import org.powermock.api.easymock.PowerMock;

我希望这个答案是明确和完整的

顺便说一句,我会向您推荐一些有用的链接:

GitHub 上的 PowerMock 静态文档

Mvn 存储库 PowerMock 库

再见 :D

于 2016-06-27T10:04:45.590 回答