我试图在使用PowerMock的测试中模拟java ServicesLoader
(final
),它似乎失败了......
重现错误的最简单的测试用例是:
import java.util.ServiceLoader;
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;
@RunWith(PowerMockRunner.class)
@PrepareForTest(ServiceLoader.class)
public class ServiceLoaderTest {
@Test
public void testServiceLoaderMock() {
ServiceLoader mock = PowerMock.createMock(ServiceLoader.class);
}
}
我得到的例外是:
-------------------------------------------------------------------------------
Test set: ServiceLoaderTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.407 sec <<< FAILURE!
testServiceLoaderMock(ServiceLoaderTest) Time elapsed: 0.359 sec <<< ERROR!
java.lang.IllegalAccessError: java.lang.Class
at sun.reflect.GeneratedSerializationConstructorAccessor8.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:56)
at org.powermock.reflect.internal.WhiteboxImpl.newInstance(WhiteboxImpl.java:257)
at org.powermock.reflect.Whitebox.newInstance(Whitebox.java:139)
at org.powermock.core.DefaultFieldValueGenerator.instantiateFieldType(DefaultFieldValueGenerator.java:74)
at org.powermock.core.DefaultFieldValueGenerator.fillWithDefaultValues(DefaultFieldValueGenerator.java:51)
at org.powermock.api.easymock.PowerMock.doMock(PowerMock.java:2146)
at org.powermock.api.easymock.PowerMock.createMock(PowerMock.java:98)
at ServiceLoaderTest.testServiceLoaderMock(ServiceLoaderTest.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:322)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:94)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:309)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:112)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:73)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:297)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:84)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:222)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:161)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:135)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:133)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:112)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:57)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127)
at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345)
at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1009)
我想这与对服务的Class<T>
字段进行初始化有关,但我不确定。
一旦我解决了这个问题,我还想模拟静态方法ServiceLoader.load(Class)
来返回先前创建的模拟,因此可能会有更多问题......
有关如何解决它的想法吗?
答案 0 :(得分:0)
请看一下这篇文章: Mocking static methods in java system classes ,或者更具体地说,是一个名为的部分“但是等等,这会对最终的系统类有效吗?”
引用文章:
但是最终的系统类怎么样? PowerMock无法删除系统类的最终修饰符,那该怎么办?在这些情况下,PowerMock的作用是在运行时创建一个全新的类,其结构与原始的最终系统类完全相同。即所有方法名称及其相应的签名都将复制到此新副本类中。为了允许部分模拟,副本类的所有静态方法都委托给最终系统类中的原始方法。它也是由底层模拟框架而不是原始系统类模拟的副本类。然后,MockGateway会发现绑定到此特定系统类的所有方法都应该路由到副本模拟。因此,在最终系统类(如java.lang.System或java.lang.String)中模拟静态方法也可以。作为旁注,实际上可以使用这种技术在Java中实现duck-typing。无论如何,这是一个展示我们刚刚说过的例子的例子:
public class SystemPropertyMockDemo {
public String getSystemProperty() throws IOException {
return System.getProperty("property");
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest( { SystemPropertyMockDemo.class, SystemPropertyMockDemoTest.class })
public class SystemPropertyMockDemoTest
@Test
public void demoOfFinalSystemClassMocking() throws Exception {
mockStatic(System.class);
expect(System.getProperty("property")).andReturn("my property");
replayAll();
assertEquals("my property",
new SystemPropertyMockDemo().getSystemProperty());
verifyAll();
}
}
答案 1 :(得分:0)
这似乎是一个错误。从邮件列表中得到答案:
http://groups.google.com/group/powermock/browse_thread/thread/4afafbfdf1b3ce58