PowerMock: java.lang.IllegalAccessError: java.lang.Class при издевательстве над java.util.ServiceLoader - PullRequest
5 голосов
/ 01 апреля 2011

Я пытаюсь смоделировать java ServicesLoader (то есть final) в моих тестах с PowerMock, и, похоже, он не работает ...

Простейший контрольный пример, который воспроизводит ошибку, таков:

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), чтобы вернуть ранее созданный макет, так что может возникнуть больше проблем ...

Есть идеи, как ее решить?

Ответы [ 2 ]

0 голосов
/ 05 апреля 2011

Казалось, это ошибка.Получил ответ из списка рассылки:

http://groups.google.com/group/powermock/browse_thread/thread/4afafbfdf1b3ce58

0 голосов
/ 01 апреля 2011

Посмотрите на эту статью: Пересмешивание статических методов в системных классах java , или, более конкретно, раздел под названием "Но подождите, это будет работать для окончательной системы классы? ".

Цитируется из статьи:

Но как насчет окончательного системного класса? PowerMock не может удалить окончательный модификатор системного класса, что делать? В этих случаях PowerMock создает абсолютно новый класс во время выполнения с точно такой же структурой, что и исходный конечный системный класс. То есть все имена методов и соответствующие им сигнатуры копируются в этот новый класс реплик. Чтобы разрешить частичное моделирование всех статических методов делегатов класса реплики исходному методу в конечном системном классе. Это также класс реплики, который подвергается насмешке базовой структурой mock вместо исходного системного класса. Затем MockGateway выясняет, что все методы, привязанные к этому конкретному системному классу, должны вместо этого направляться на макет реплики. Таким образом, насмешка над статическими методами в конечных системных классах, таких как java.lang.System или java.lang.String, также работает. Как примечание стороны, было бы возможно использовать эту технику, чтобы реализовать типизацию утки также в Java. Во всяком случае, вот пример, чтобы продемонстрировать то, что мы только что сказали:

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