2011-04-01 12 views
5

Estoy tratando de burlarme del java ServicesLoader (que es final) en mis pruebas con PowerMock, y parece que falla ...PowerMock: java.lang.IllegalAccessError: java.lang.Class al burlarse de java.util.ServiceLoader

el caso de prueba más simple que reproduce el error es la siguiente:

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

Y la excepción que recibo es:

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

supongo que tiene algo que ver con haces g una cierta inicialización del campo Class<T> del servicio, pero no estoy seguro.

Una vez que he fijado esto, me gustaría también para burlarse del método estático ServiceLoader.load(Class) para devolver el simulacro creado previamente, por lo que podría haber más problemas por venir ...

alguna idea sobre cómo se puede solucionar?

Respuesta

0

Tener un vistazo a este artículo: Mocking static methods in java system classes, o más específicamente, la sección llamada "Pero espera, es que esto funciona para las clases del sistema final?".

citado del artículo:

But what about a final system class? There's no way for PowerMock to remove the final modifier of a system class so what to do? What PowerMock does in these cases is to create a completely new class at run-time with the exact same structure as the original final system class. I.e. all method names and their corresponding signature are copied to a this new replica class. To allow for partial mocking all static methods of the replica class delegates to the original method in the final system class. It's also the replica class that is being mocked by the underlying mock framework instead of the original system class. The MockGateway then figures out that all methods bound for this particular system class should be routed to the replica mock instead. Thus mocking of static methods in final system classes such as java.lang.System or java.lang.String works as well. As a side note it would actually be possible to use this technique to implement duck-typing in Java as well. Anyway, here's an example to demonstrate what we've just said:

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(); 
    } 
} 
+0

sigue fallando durante la creación de la maqueta ejemplo ServiceLoader (las obras simuladas estáticas finas): - / – fortran

Cuestiones relacionadas