Mockito + PowerMock LinkageError beim Spotten der Systemklasse

Lesezeit: 7 Minuten

Benutzer-Avatar
Wojciech Reszelewski

Ich habe so ein Code-Snippet:

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

Während ich diese Tests durchführte, bekam ich:

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)

Wisst ihr wie ich das verhindern kann? Vielleicht gibt es eine andere Möglichkeit, ein solches Stück Code zu verspotten:

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

  • Was versuchst du zu verspotten? Und warum?

    – NilsH

    13. Mai 2013 um 11:16 Uhr

  • Der erste Test ist Getter- und Setter-Test, ich rufe dort den Konstruktor auf (und dort tritt die Ausnahme auf). Der zweite ist der Konstruktortest. Ich möchte die Kontrolle darüber erhalten, welche Ressourcenaufzählung im dritten Codeausschnitt enthalten ist.

    – Wojciech Reszelewski

    13. Mai 2013 um 11:20 Uhr

  • Zunächst einmal scheint es mir, dass Ihre Tests sehr eng an Ihre Implementierung gekoppelt sind. Erfahrungsgemäß führt dies zu fragilen Tests. Vorzugsweise möchten Sie beim Schreiben Ihrer Tests “Black Box” denken. „Was soll dieses Stück Code tun“, anstatt „Wie macht dieses Stück Code es?“. Zweitens denke ich, dass Sie besser dran wären, nur eine Reihe von Ressourcen zu erstellen und die Java-Laufzeit sich um das Klassenladen selbst kümmern zu lassen.

    – NilsH

    13. Mai 2013 um 11:22 Uhr


  • Es ist möglich, verschiedene Sätze von Ressourcen zu erstellen, da sie Testfälle waren?

    – Wojciech Reszelewski

    13. Mai 2013 um 11:30 Uhr

  • Sicher. Am einfachsten ist es für Sie wahrscheinlich, den Namen der Ressourcen zu parametrisieren. Dann können Sie verschiedene Ressourcennamen an Ihre Tests übergeben.

    – NilsH

    13. Mai 2013 um 11:34 Uhr

Benutzer-Avatar
crandrad

Versuchen Sie, diese Anmerkung zu Ihrer Testklasse hinzuzufügen:

@PowerMockIgnore("javax.management.*")

Hat für mich funktioniert.

  • Genauigkeit * “zu Ihrer Testklasse”. Einfache und nützliche Antwort!

    – pdem

    19. November 2015 um 10:09 Uhr

  • Geht das auch per Code oder Konfiguration? Ich konnte keine Möglichkeit finden, dies zu tun. Wir haben Hunderte von Tests … ich kann sie nicht alle anpassen.

    – Friedrich Leitenberger

    11. Juli 2017 um 18:01 Uhr

  • @FredericLeitenberger siehe meine Antwort unten

    – Benutzer3474985

    3. Januar 2019 um 23:43 Uhr

  • Können Sie bitte auch die Intuition und Bedeutung dieses Fixes erklären? Welche Anweisung geben wir PowerMockito mit dieser Zeile?

    – Swapnil B.

    5. Oktober 2019 um 1:41 Uhr

Benutzer-Avatar
Jason D

Ähnlich wie bei der akzeptierten Antwort hier musste ich schließlich alle SSL-bezogenen Klassen ausschließen:

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

Das Hinzufügen an die Spitze meiner Klasse hat den Fehler behoben.

  • Es müssen noch weitere Pfade hinzugefügt werden, aber du hast mein Leben gerettet, Mann! @PowerMockIgnore({"javax.management.*", "org.apache.http.conn.ssl.*", "com.amazonaws.*", "javax.net.ssl.*","com.sun.*"})

    – Francisco López-Sancho

    4. August 2016 um 12:29 Uhr


  • Gut zu wissen auch über com.sun.

    – Jason D

    4. August 2016 um 14:04 Uhr

  • Ich brauchte Folgendes: @PowerMockIgnore({“javax.management.*”, “javax.crypto.*”})

    – Kristof Neirynck

    12. Juni 2017 um 10:29 Uhr


  • Dieser hat mich gerettet: @PowerMockIgnore({“javax.management.*”, “org.apache.http.*”, “com.amazonaws.http.conn.ssl.*”, “javax.net.ssl.*” , “com.sun.*”, “javax.xml.*”, “javax.crypto.*”})

    – Fayaz Ahmed

    5. April 2019 um 0:22 Uhr

Benutzer-Avatar
烬哥哥

Klassenlader Konflikt, verwenden Sie dies: @PowerMockIgnore("javax.management.*")

Lassen Schein-Klassenlader nicht laden javax.*.
Es klappt.

  • Nach dem Gebrauch @PowerMockIgnore("javax.management.*"), die Testklasse funktioniert gut einzeln. Aber läuft so Junit test auf diesem Paket habe Failed to load ApplicationContext Error. org.apache.catalina.LifecycleException: A child container failed during start usw.

    – niaomingjian

    22. Mai 2017 um 10:23 Uhr


Dies ist vielleicht ein etwas altes Thema, aber ich bin auch auf dieses Problem gestoßen. Es stellt sich heraus, dass einige der Java-Versionen Powermockito nicht verarbeiten können, wenn Powermock herausfindet, dass es 2 Klassen mit demselben Namen im selben Paket gibt (über verschiedene Abhängigkeiten).

Bei jeder Version höher als Java 7_25 gibt es diesen Fehler.

In PowerMock 1.7.0 kann dem Klassenpfad Ihres Projekts eine benutzerdefinierte globale Konfiguration hinzugefügt werden. PowerMockConfig

org/powermock/extensions/configuration.properties

Fügen Sie einfach eine Zeile in der Eigenschaftendatei hinzu wie:

powermock.global-ignore=javax.management.*

Dadurch wird der Fehler für alle Testklassen in Ihrem Projekt behoben.

  • Beachten Sie, dass Leerzeichen und doppelte Anführungszeichen in der Datei configuration.properties nicht zulässig sind. Sehen: github.com/powermock/powermock/issues/989

    – Navitron

    28. September 2021 um 8:38 Uhr


Benutzer-Avatar
versuchen-fangen-endlich

Um Systemklassen zu simulieren, bereiten Sie die Klasse vor, die das Ziel des Tests ist, not Thread.class. PowerMock kann auf keinen Fall instrumentieren Thread.class da es während des JVM-Starts erforderlich ist – lange bevor PowerMock instrumentieren kann.

So wie die Instrumentierung funktioniert, kann eine Klasse, sobald sie geladen ist, nicht mehr instrumentiert werden.

Sehen das PowerMock-Wiki.

  • Beachten Sie, dass Leerzeichen und doppelte Anführungszeichen in der Datei configuration.properties nicht zulässig sind. Sehen: github.com/powermock/powermock/issues/989

    – Navitron

    28. September 2021 um 8:38 Uhr


Benutzer-Avatar
David Georg Reichelt

Abhängig von Ihrem individuellen Setup kann es erforderlich sein, weitere Methoden hinzuzufügen @PowerMockIgnore. Ich bin bei slf4j darüber gestolpert, um PowerMock und slf4j zusammen zu verwenden, benötigen Sie

@PowerMockIgnore({ "com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*", "org.w3c.dom.*" })

  • Im Vergleich zu anderen Beispielen von @PowerMockIgnore dieser hat bei mir funktioniert, wegen der "org.xml.*" Eintrag. Andere mit diesem Problem sollten prüfen, welche Signaturprobleme von PowerMock ausgehen und diese Pakete mit der Anmerkung ignorieren.

    – Webchen

    30. November 2021 um 9:53 Uhr

1352280cookie-checkMockito + PowerMock LinkageError beim Spotten der Systemklasse

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy