Mocking core Java classes with jmockit
I know, I know. Java. Blech!
But if you have to work in Java, instead of something more elegant like Ruby, wouldn’t you like some of the same awesome mocking power that you have come to know and love in Java? Yeah, me too.
Toby DiPasquale turned me on to jmockit. It’s a little framework that provide RSpec-like mocking in Java. To those familiar with RSpec: jmockit allows developers to mock constructors as well as individual method on live objects. It accomplishes this courtesy of the java.lang.instrument package that was added in Java 1.5.
I was curious to see if it is possible to mock boot classloader loaded classes (i.e., java.lang.Integer, etc.). After a few minutes of tinkering, I found a way but it’s none to pleasant…
The primary annoyance is this: the core Java mocks appear to have to be in the bootclasspath. Why? I speculate however I believe the JVM needs the definition when the class is initial loaded – which, for core classes, can often happen at startup.
So, for example, this works:
Test.java:
import mockit.*;
import java.math.*;
public class Test {
public static void main(String[] args) {
Mockit.redefineMethods(BigDecimal.class, new BigDecimalMock());
System.err.println(BigDecimal.ONE.add(BigDecimal.ONE));
}
}
BigDecimalMock.java:
import java.math.*;
public class BigDecimalMock {
public BigDecimal add(BigDecimal v) {
return new BigDecimal("42");
}
}
And run the whole beast with this:
java -Xbootclasspath/a:jmockit.jar:-javaagent:jmockit.jar Test
So, yes, Virginia, it is possible to mock core classes. But does it suck? Hell, yes. To make this work practically would likely necessitate launching a separate VM so as to “scope” the mock to a particular test.
Fugly.
Posted by evan on Friday, May 02, 2008
blog comments powered by Disqus
My name is Evan Light and, yes, I am a nerd. I'm also a professional software developer who, after spending one too many years contracting to the federal government, escaped into the far more enjoyable commercial world. Having spent several years using C and even more using Java (the latter very nearly caused me to give up programming entirely), I consider myself fortunate to have discovered Ruby and to use it as part of my daily work.