Hi guys,
Doing some testing on a class that has a simple JMX initializer like
so:
final MBeanServer mbs =
ManagementFactory.getPlatformMBeanServer();
ObjectName name = new ObjectName("hbase:" +
"service=Thrift,name=" + Thread.currentThread().getName());
mbs.registerMBean(this, name);
When I run my test I get an error:
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"
This exception line comes from the "ObjectName name = ..." line...
whoa!
So I decide I can be clever in the test set-up:
MBeanServer mbeanMock = PowerMockito.mock(MBeanServer.class);
PowerMockito.mockStatic(ManagementFactory.class);
when(ManagementFactory.getPlatformMBeanServer()).thenReturn(mbeanMock);
PowerMockito.whenNew(ObjectName.class).withArguments(any())
.thenReturn(null); // null object
So this looks ok - we replace the mbs with a mock which noops, also we
return a bogus ObjectName that is null. Essentially the entire section
of code is faked (in the original listing).
But now I get a very mysterious error:
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
MBeanServer$$EnhancerByMockitoWithCGLIB$$215731b3 cannot be returned
by getPlatformMBeanServer()
getPlatformMBeanServer() should return MBeanServer
I run the debugger, and we are ultimately failing here:
AnswersValidator.java:57:
if (!answer.returnsNull() && !
invocation.isValidReturnType(answer.getReturnType())) {
reporter.wrongTypeOfReturnValue(invocation.printMethodReturnType(),
answer.printReturnType(), invocation.getMethodName());
}
The call invocation.isValidReturnType returns false. The method looks
like so:
public boolean isValidReturnType(Class clazz) {
if (method.getReturnType().isPrimitive()) {
return Primitives.primitiveTypeOf(clazz) ==
method.getReturnType();
} else {
return method.getReturnType().isAssignableFrom(clazz);
}
}
Inside the debugger we take the second path. clazz is a CGLIB mocked
up MBeanServer mock that in it's interface list implements
javax.management.MBeanServer. method.getReturnType() is Class for
javax.management.MBeanServer. This call 'isAssignableFrom' returns
false. That is the mock is apparently not assignable to the class.
This simple unit test:
MBeanServer mbeanMock = Mockito.mock(MBeanServer.class);
Class<MBeanServer> clazz = MBeanServer.class;
System.out.println(clazz.isAssignableFrom(mbeanMock.getClass()));
prints 'true'.
I made another unit test that isolates these things:
@RunWith(PowerMockRunner.class)
@PrepareForTest( { ManagementFactory.class })
public class TestRyan extends TestCase {
public void testSimple() throws Exception {
MBeanServer mbeanMock = PowerMockito.mock(MBeanServer.class);
PowerMockito.mockStatic(ManagementFactory.class);
when(ManagementFactory.getPlatformMBeanServer()).thenReturn(mbeanMock);
}
}
and this fails with and without the @PrepareForTest line. With the
line I get the WrongTypeOfReturnValue. Without the line I get a
different kind of error.
As for my environment... I am running Java6 with IntelliJ on my mac.
I'll try a linux machine asap. My classpath is pretty big, and it
includes some usual suspects (its the classpath of the Apache HBase
project FYI):
- commons-logging-api-1.0.4
- log4j-1.2.15
- all the mockito and powermock dependencies
- many many more.
I also looked at
http://code.google.com/p/powermock/wiki/MockSystem
indicating that I should PrepareForTest the calling class (I am but I
dont even get that far) and includes an easyMock style code snippet.
Could the problem be related to my use of the Mockito interface of
Powermock? Should I try easyMock?
My initial problem was "how do I run mockito on a class that also
initializes a JMX mbean/dynamic bean". I would still like to answer
that one - the only hits I get with the error message come from my own
project's JIRA indicating that PowerMock doesnt work for the
aforementioned reason.
--
You received this message because you are subscribed to the Google Groups "PowerMock" group.
To post to this group, send email to
powe...@googlegroups.com.
To unsubscribe from this group, send email to
powermock+...@googlegroups.com.
For more options, visit this group at
http://groups.google.com/group/powermock?hl=en.