模拟静态方法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();
}
}
例外情况是:
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)
如何模拟staic方法,而m使用powerMock我正在使用intelliJ的想法,如何解决该异常。
您的代码缺少注释
@PrepareForTest(IdGenerator.class)
在我的情况下,我在测试类中缺少以下方法
@ObjectFactory
/**
* Configure TestNG to use the PowerMock object factory.
*/
public IObjectFactory getObjectFactory() {
return new org.powermock.modules.testng.PowerMockObjectFactory();
}
一旦我添加了它,我就消除了"没有最后一次调用模拟可用"的错误。
您需要将重播放在对方法的实际调用之前。
编辑:我认为部分问题可能是由于你们的进口产品造成的。尽量不要导入静态powermock和静态easymock(我发现我经常混淆自己,忘记了需要调用哪一个重播)。
请尝试运行以下代码。如果它没有正确运行,那么可能是因为您的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);
}
}
IdGenerator:
public class IdGenerator {
public static long generateNewId()
{
return System.currentTimeMillis();
}
}
服务注册人:
public class ServiceRegistrator {
public long registerService()
{
long id = IdGenerator.generateNewId();
return id;
}
}
这个问题已经存在很长时间了,但我会给它一个答案来解释我为解决这个问题做了什么。
首先,你必须使用这两个注释:
@RunWith(PowerMockRunner.class)
这个注释让当前的测试类知道用什么来运行他的测试,这很有用,因为我们可以使用PowerMockRunner而不是JUnitRunner
@PrepareForTest(IdGenerator.class)
这个注释用于准备要在测试中使用的类"IdGenerator",prepare意味着我们将能够像对公共方法那样模拟静态方法
在添加了这两个注释之后,我们必须确保我们使用的是PowerMock提供的正确包:
1) PowerMock:
- 导入:导入org.powermock.api.easymock.powermock
-
使用:我们将使用PowerMock来模拟(不仅如此)我们的静态方法,并使用以下代码行
PowerMock.mockStatic(IdGenerator.class);
2) EasyMock:
- 导入:导入org.easymock.easymock
-
使用:我们将使用EasyMock来伪造我们的对象,以通过我们的静态方法返回:
EasyMock.expect(IdGenerator.generateNewId()).和Return(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
请注意,在创建将调用静态faked方法的新对象(本例中为actualId)之前,必须使用重播。
也要注意你正在导入的内容,为了分散注意力,我使用了
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