PowerMock:: [java.lang.IllegalStateException: 没有可用的模拟的最后一次调用]

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17293780/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 01:36:28  来源:igfitidea点击:

PowerMock:: [java.lang.IllegalStateException: no last call on a mock available]

javaunit-testingjuniteasymockpowermock

提问by SachG

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

模拟静态方法 powermock 在 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.

如何模拟静态方法,而 m 使用 powerMock 我正在使用智能想法,如何解决该异常。

回答by JoseK

Your code is missing the annotation

您的代码缺少注释

@PrepareForTest(IdGenerator.class)

回答by gybrush

In my case I was missing the following method in my test class

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

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

Once I added it, I got rid of the "no last call on a mock available" error.

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

回答by gybrush

This question has been here for a long time but I'll try to give to it an aswer to explain what i did to resolve this problem.

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

First of all you have to use these two annotations:

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

@RunWith(PowerMockRunner.class)

@RunWith(PowerMockRunner.class)

This annotation let the current test class know what to use to run his tests, this is useful because we can use PowerMockRunner instead of JUnitRunner

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

@PrepareForTest(IdGenerator.class)

@PrepareForTest(IdGenerator.class)

This annotation is used to prepare the class "IdGenerator" to be used in the test, prepare means that we will be able to mock the static methods as we do to the public methods

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

After added these two annotations we have to be sure we are using the right packages provided by PowerMock:

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

1) PowerMock:

1)PowerMock:

  • Import: import org.powermock.api.easymock.PowerMock;
  • Use: We will use PowerMock to mock (and not only) our static method with the following code line

    PowerMock.mockStatic(IdGenerator.class);

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

    PowerMock.mockStatic(IdGenerator.class);

2) EasyMock:

2)EasyMock:

  • Import: import org.easymock.EasyMock;
  • Use: We are going to use EasyMock to fake our object to be returned by our static method:

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

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

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

These was two examples on what are used PowerMock and EasyMock, and here I'll try to explain the code and what it does:

这是关于使用 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

Pay attention because replay must be used before you create the new object (actualId in this example) that will call the static faked methods.

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

Also do a lot of attention on what you are importing, for a distraction i was using

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

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

Instead of

代替

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

I hope that this answer is clear and complete

我希望这个答案是清楚和完整的

By the way here i'll refer you to some useful links:

顺便说一下,我会在这里向您推荐一些有用的链接:

PowerMock Static Documentation on GitHub

GitHub 上的 PowerMock 静态文档

Mvn Repository PowerMock Libraries

Mvn 存储库 PowerMock 库

See you :D

见 :D

回答by HardcoreBro

You need to put the replay before the actual call to the method.

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

EDIT: I think part of the problem may be caused because of your imports. Try not to import static powermock and static easymock (I've found that I often confuse myself and forget which one I need to call replay on).

编辑:我认为部分问题可能是由于您的进口造成的。尽量不要导入 static powermock 和 static easymock(我发现我经常混淆自己并忘记我需要调用哪个重放)。

Try running the following code. If it doesn't run correctly, then it may be because of a problem with the particular version of PowerMock/EasyMock/Junit that you have.

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

TestClass:

测试类:

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

IdGenerator:

身份生成器:

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

ServiceRegistrator:

服务注册器:

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