Igor Kromin |   Consultant. Coder. Blogger. Tinkerer. Gamer.

Recently at work a big amount of effort has been put in to adding unit tests for as much code as possible. Due to the nature of the services that we work with, we required to make heavy use of PowerMock. It's a great framework that lets us mock out certain classes that are usually hard to mock, like statics, and unfortunately at one point I started to see LinkageError exceptions being thrown that looked like this...
 Exception
WARNING: Error while registering Oracle JDBC Diagnosability MBean.
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:763)
at org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:262)
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:206)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass1(DeferSupportingClassLoader.java:89)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:79)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at oracle.jdbc.driver.OracleDriver.registerMBeans(OracleDriver.java:360)
at oracle.jdbc.driver.OracleDriver$1.run(OracleDriver.java:199)
at java.security.AccessController.doPrivileged(Native Method)
at oracle.jdbc.driver.OracleDriver.<clinit>(OracleDriver.java:195)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:380)
at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
at java.sql.DriverManager$2.run(DriverManager.java:603)
at java.sql.DriverManager$2.run(DriverManager.java:583)
at java.security.AccessController.doPrivileged(Native Method)
at java.sql.DriverManager.loadInitialDrivers(DriverManager.java:583)
at java.sql.DriverManager.<clinit>(DriverManager.java:101)


So what does this mean? Well PowerMock prepares and loads mocked classes using its MockClassLoader. In some cases this behaviour is undesirable and the mocked class must be loaded by the system class loader instead. This is easily done with the PowerMockIgnore annotation like this...
 Java
...
@PowerMockIgnore("javax.management.*")
public class MyTestClass {
...
}


So in my case since the LinkageError was for the javax/management/MBeanServer class, I use the "javax.management.*" value to make sure that everything in the javax.management package is deferred to the system class loader (I could have used the specific class but I chose to use the entire package).

There is a way to apply this type of configuration globally by creating a file, "org/powermock/extensions/configuration.properties", and adding it to the classpath (if using Maven in the src/test/resources directory). The configuration file is a standard Java Properties file and needs to have the "powermock.global-ignore" set the same way as the annotation, however I couldn't get this to work.



-i

Skip down to comments...
Hope you found this post useful...

...so please read on! I love writing articles that provide beneficial information, tips and examples to my readers. All information on my blog is provided free of charge and I encourage you to share it as you wish. There is a small favour I ask in return however - engage in comments below, provide feedback, and if you see mistakes let me know.

If you want to show additional support and help me pay for web hosting and domain name registration, donations, no matter how small, are always welcome!

Use of any information contained in this blog post/article is subject to this disclaimer.
 
comments powered by Disqus
Other posts you may like...