web-dev-qa-db-fra.com

Mockito + PowerMock LinkageError en moquant la classe système

J'ai un tel extrait de code:

@RunWith(PowerMockRunner.class)
@PrepareForTest({Thread.class})
public class AllMeasuresDataTest {

@Before
public void setUp() throws Exception {
}

@Test
public void testGetMeasures() {
    AllMeasuresData measure = new AllMeasuresData();
    assertEquals(measure.getMeasures(), null);
    HashMap<String, Measure> map = new HashMap<String, Measure>();
    measure.setMeasures(map);
    assertEquals(measure.getMeasures(), map);
    measure.setMeasures(null);
    assertEquals(measure.getMeasures(), null);
}

@Test
public void testAllMeasuresData() throws IOException {
    ClassLoader loader = PowerMockito.mock(ClassLoader.class);
    Thread threadMock = PowerMockito.mock(Thread.class);
    Vector<URL> vec = new Vector<URL>();
    Mockito.when(loader.getResources("measure")).thenReturn(vec.elements());
    Mockito.when(threadMock.getContextClassLoader()).thenReturn(loader);
    PowerMockito.mockStatic(Thread.class);
    Mockito.when(Thread.currentThread()).thenReturn(threadMock);
        ...
    }
}

En exécutant ces tests, j'ai eu:

Java.lang.LinkageError: loader constraint violation: loader (instance of org/powermock/core/classloader/MockClassLoader) previously initiated loading for a different type with name "javax/management/MBeanServer"
at Java.lang.ClassLoader.defineClass1(Native Method)
at Java.lang.ClassLoader.defineClass(ClassLoader.Java:791)
at Java.lang.ClassLoader.defineClass(ClassLoader.Java:634)
at org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.Java:201)
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.Java:149)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.Java:67)
at Java.lang.ClassLoader.loadClass(ClassLoader.Java:356)
at org.codecover.instrumentation.Java.measurement.ProtocolImpl.initializeMBean(ProtocolImpl.Java:247)
at org.codecover.instrumentation.Java.measurement.ProtocolImpl.<init>(ProtocolImpl.Java:237)
at org.codecover.instrumentation.Java.measurement.ProtocolImpl.getInstance(ProtocolImpl.Java:185)
at measure.CodeCoverCoverageCounter$6ya5ud0ow79ijrr1dvjrp4nxx60qhxeua02ta2fzpmb1d.<clinit>(MeasureCalculatorsHolder.Java:146)
at measure.MeasureCalculatorsHolder.<clinit>(MeasureCalculatorsHolder.Java:17)
at Java.lang.Class.forName0(Native Method)
at Java.lang.Class.forName(Class.Java:188)
at javassist.runtime.Desc.getClassObject(Desc.Java:43)
at javassist.runtime.Desc.getClassType(Desc.Java:152)
at javassist.runtime.Desc.getType(Desc.Java:122)
at javassist.runtime.Desc.getType(Desc.Java:78)
at algorithm.AllMeasuresDataTest.testGetMeasures(AllMeasuresDataTest.Java:26)
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:57)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
at Java.lang.reflect.Method.invoke(Method.Java:601)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.Java:66)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.Java:312)
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:296)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit49RunnerDelegateImpl$PowerMockJUnit49MethodRunner.executeTestInSuper(PowerMockJUnit49RunnerDelegateImpl.Java:116)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit49RunnerDelegateImpl$PowerMockJUnit49MethodRunner.executeTest(PowerMockJUnit49RunnerDelegateImpl.Java:77)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.Java:284)
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:209)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.Java:148)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.Java:122)
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:120)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.Java:101)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.Java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.Java:53)
at org.Eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.Java:50)
at org.Eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.Java:38)
at org.Eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.Java:467)
at org.Eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.Java:683)
at org.Eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.Java:390)
at org.codecover.juniteclipse.runner.EclipseTestRunner.main(EclipseTestRunner.Java:40)

Savez-vous comment puis-je empêcher cela? J'ai peut-être une autre façon de se moquer d'un tel code:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
...
Enumeration<URL> resources = classLoader.getResources(path);
141

Essayez d'ajouter cette annotation à votre classe de test:

@PowerMockIgnore("javax.management.*")

Travaillé pour moi.

357
crandrad

Chargeur de classe conflit, utilisez ceci: @PowerMockIgnore("javax.management.*")

Soit chargeur de classe fictif ne charge pas javax.*. Ça marche.

26
烬哥哥

Semblable à la réponse acceptée ici, j'ai fini par devoir exclure toutes les classes liées à SSL:

@PowerMockIgnore({"javax.management.*", "org.Apache.http.conn.ssl.*", "com.amazonaws.http.conn.ssl.*", "javax.net.ssl.*"})

Ajouter cela au sommet de ma classe a résolu l'erreur.

23
Jason D

C'est peut-être un vieux sujet, mais j'ai aussi rencontré ce problème. Il s'avère que certaines des Java ne peuvent pas gérer powermockito lorsque powermock découvre qu'il existe 2 classes portant le même nom dans le même package (sur différentes dépendances).

Avec toute version supérieure à Java 7_25, cela donne cette erreur.

7
Rens Groenveld

Afin de simuler des classes système, préparez la classe qui est la cible du test et non pas Thread.class. PowerMock ne pourra en aucun cas instrumenter Thread.class parce que cela est nécessaire au démarrage de la machine virtuelle - bien avant que PowerMock puisse instrumenter.

Le fonctionnement de l'instrumentation, une fois qu'une classe est chargée, ne peut plus être importée.

Voir le wiki PowerMock .

3
ash

Dans PowerMock 1.7.0, une configuration globale définie par l'utilisateur peut être ajoutée au chemin de classe de votre projet. PowerMockConfig

org/powermock/extensions/configuration.properties

Ajoutez simplement une ligne dans le fichier de propriétés comme suit:

powermock.global-ignore=javax.management.*

Cela résoudra l'erreur pour toutes les classes de test de votre projet.

3
user3474985