199

I've got such a 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);
        ...
    }
}

While running this tests I got:

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)

Do you know how can I prevent this? I maybe there is another way to mock such a piece of code:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
...
Enumeration<URL> resources = classLoader.getResources(path);
Krease
  • 15,805
  • 8
  • 54
  • 86
Wojciech Reszelewski
  • 2,656
  • 2
  • 18
  • 27
  • What is it you're trying to mock? And why? – NilsH May 13 '13 at 11:16
  • First test is getters and setters test, I'm calling constructor there (and there the exception occurs). The second one is constructor test. I want to get control of what resources enumeration contains in third code snippet. – Wojciech Reszelewski May 13 '13 at 11:20
  • 1
    First of all, it looks to me that your tests are very tightly coupled to your implementation. By experience, this will lead to fragile tests. Preferrably, you want to think "black box" when writing your tests. "What is this piece of code supposed to do", rather than "How is this piece of code doing it". Second, I think you'd be better off just creating a set of resources and let the Java runtime deal with the classloading itself. – NilsH May 13 '13 at 11:22
  • It is possible to create various sets of resources, as they where test cases? – Wojciech Reszelewski May 13 '13 at 11:30
  • Sure. The easiest for you is probably to parametrize the name of the resources. Then you can pass different resource names into your tests. – NilsH May 13 '13 at 11:34
  • You mean creating another method with new parameters? It's strange, but I'm writing tests for project that's already complete, but tests are missing, so it's not so easy in that case. – Wojciech Reszelewski May 13 '13 at 11:56

7 Answers7

483

Try adding this annotation to your Test class:

@PowerMockIgnore("javax.management.*")

Worked for me.

crandrad
  • 5,081
  • 1
  • 17
  • 7
38

Similar to the accepted response here, I ended up having to exclude all of the SSL related classes:

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

Adding that to the top of my class resolved the error.

Jason D
  • 8,023
  • 10
  • 33
  • 39
29

Classloader conflict, use this: @PowerMockIgnore("javax.management.*")

Let mock classloader do not load javax.*. It works.

Logan Wayne
  • 6,001
  • 16
  • 31
  • 49
烬哥哥
  • 311
  • 3
  • 4
  • After using `@PowerMockIgnore("javax.management.*")`, the test class works well singly. But running as `Junit test` on that **package** got `Failed to load ApplicationContext` error. `org.apache.catalina.LifecycleException: A child container failed during start` and so on. – niaomingjian May 22 '17 at 10:23
8

This may be a bit of an old topic, but I have also ran into this problem. Turns out that some of the java versions cannot handle powermockito when powermock finds out there are 2 classes with the same name in the same package (over different dependencies).

With any version higher than Java 7_25 it gives this error.

Rens Groenveld
  • 960
  • 11
  • 28
  • 2
    "With any version higher than Java 7_25 it gives this error.", This is informative. – Kajal Sinha Jun 16 '16 at 02:08
  • What it means: "cannot handle powermockito"? Is there any way to deal with it besides ignoring by annotation? – Line May 19 '17 at 07:27
  • It's a long time ago, but I think we sorted it out by making sure there are not 2 classes with the same name in the same kind of package. Of course, if you have 2 libraries you depend on, and they reside in there... it is going to be difficult. I don't know if this issue has been fixed in the meantime. – Rens Groenveld May 19 '17 at 11:28
8

In PowerMock 1.7.0 a user-defined global configuration can be added to your project's classpath. PowerMockConfig

org/powermock/extensions/configuration.properties

Simply add a line in the properties file like:

powermock.global-ignore=javax.management.*

This will resolve the error for all the test classes in your project.

user3474985
  • 983
  • 8
  • 20
  • Note, spaces and double quotes are not allowed in the configuration.properties file. See: https://github.com/powermock/powermock/issues/989 – Navigatron Sep 28 '21 at 08:38
5

In order to mock system classes, prepare the class that is the target of the test, not Thread.class. There's no way PowerMock will be able to instrument Thread.class because it is required during JVM startup - well before PowerMock can instrument.

The way instrumentation works, once a class is loaded, it can no longer be intstrumented.

See the PowerMock wiki.

try-catch-finally
  • 7,436
  • 6
  • 46
  • 67
ash
  • 4,867
  • 1
  • 23
  • 33
5

Depending on your individual setup, it may be necessary to add more methods to @PowerMockIgnore. I stumbled over this with slf4j, for using PowerMock and slf4j together, you'll need

@PowerMockIgnore({ "com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*", "org.w3c.dom.*" })
David Georg Reichelt
  • 963
  • 1
  • 15
  • 36
  • Compared to other examples of `@PowerMockIgnore` , this one worked for me, because of the `"org.xml.*"` entry. Others with this issue should check, which signature issues arise from PowerMock and Ignore those packages with the annotation. – Webchen Nov 30 '21 at 09:53