meme: an idea, behavior, or usage that spreads from person to person within a culture agora: a gathering place

Welcome to Neal's gathering place for ideas.

Wednesday, October 17, 2007

Mocking JRuby

Testing is one of the easy ways to sneak JRuby into your organization because it is easier to write tests in dynamic languages (especially mock object tests) and it isn't code that is deployed, so it eases the minds of the furniture police somewhat. Here is an example, adapted from Martin Fowler's essay on mock object testing.

In Martin's example, he creates Order and Warehouse classes (and a Warehouse interface), then writes tests with them in jMock. Here is one of those tests, rewritten in JRuby, using the Mocha mocking library:

The order object is a pure Java object, tested with a mocked out version of the Warehouse interface. Now, this isn't exactly what Martin wrote in in excellent essay about mocks vs. stubs, but the intent is preserved in this example.

Most of the really crufty stuff in mock objects in Java is getting the compiler to agree with you that the mock object type is what you want it to be, and of course that problem goes away in JRuby. Also notice that I can create the mock object directly off the interface. Because JRuby creates proxy objects for the Java classes, you can create a mock from the interface directly by calling the new method on it. The other cool thing about this example is the require "Warehouse.jar" line at the top. JRuby allows you to require a JAR file, which gives you access to the Java classes within it.

4 comments:

What about refactoring? The biggest complaint about jMock 1 (now addressed in jMock 2) was that expectations were difficult to refactor. Doesn't this approach of using JRuby extend that problem to the entire test suite?

Refactoring is generally weaker in Ruby (although getting better, I doubt it will ever be as good as Java or other static languages). Thus, this code is harder to refactor than the corresponding jMock code. But, you can't have everything, so you get to pick: cleaner, easier mocks with a dynamic language or refactorability with jMock.

The most relevant part of a dynamic language is the doesNotUnderstand/missingMethod (or whatever it is in Ruby) hook. Tim Mackinnon's Smalltalk mock library is a model of brevity because of the use he could make of blocks.