Overriding Java methods in Groovy for unit testing

Lately, I’ve been experimenting with writing unit tests in Groovy to test our Java code at Orbitz. Groovy provides many nice language features that have the potential to dramatically reduce the amount of test code that you have to write, and to decrease the maintenance burden of that test code. Since it makes tests easier to write and maintain, hopefully more people will do it! :)

One of the features of Groovy that immediately caught my attention was the ability to specify a new implementation for a method of a given class at runtime. I was first introduced to such power by Ruby, and have been wanting it elsewhere ever since. I immediately thought that this would be great for testing our legacy code, where stubbing methods is difficult, yet often necessary to avoid major refactoring work. Changes involving major refactoring take much more time and increase the possibility of introducing more bugs. This codebase is in the middle of being swapped out with a new one, so a major refactoring isn’t really worth the effort (it would however be worth the effort in the new codebase). Currently, to stub out private methods buried in our codebase, we’ve been widening the accessibility of the method to protected, and subclassing the class to override the functionality. I’m sure this seems hacky, but it’s really less risky/evil then some of the alternatives. The code under test in this case is back end code that is not available outside of our team. Obviously, widening the scope on a method of a released API or library would be a different scenario entirely. So, I was really excited to think that Groovy could possibly help us with this nastiness.

Sound too good to be true? Well, it is.

This great feature is only available for Groovy objects! Java objects need not apply. You can add methods to Java classes, but you can’t change them. Bummer.

While scouring the web to see if there was any other way to do this, I stumbled upon JMockit, a library that helps with unit testing in Java. JMockit lets you do exactly what I want to do; provide a new implementation for any method on a class! Private methods, static methods…no sweat. JMockit to the rescue!

Right? Wrong.

Exception in thread "main" mockit.RealMethodNotFoundForMockException:
Corresponding real methods not found for the following mocks:
groovy.lang.MetaClass getMetaClass(),
Object invokeMethod(String, Object),
Object getProperty(String),
void setProperty(String, Object),
void setMetaClass(groovy.lang.MetaClass)

With JMockit, the mock object containing the new implementation must not include any new methods that are not on the original class. The problem here is that all objects in Groovy contain several methods that are not on java.lang.Object. So, even though you are not programmatically adding methods to the mock that aren’t on the original, since your object is automatically a GroovyObject, it has these new Groovy methods, whether you want them or not. And, specifically extending java.lang.Object doesn’t help either. So, back to square one.

But, all hope is not lost. Sure, it sucks that we’re reduced back to widening the accessibility of a method so it can be stubbed out in a subclass, but at least doing this is much easier in Groovy. Take the following Java class for example:

public class Book {
    public String read() {
        return getLine();
    }   

    private String getLine() {
        return "Damn this is a long book!";
    }
}

What if we want to have getLine return something different? Well, first we have to make it protected:

    protected String getLine() {
        return "Damn this is a long book!";
    }

Then, we have to subclass Book and provide the new implementation. The easiest way to do this in Java would be with an anonymous inner class:

Book b = new Book() {
    protected String getLine() {
        return "Short book";
    }
};
assertEquals("Short book", b.read());

This is much more concise in Groovy, thanks to closures, map coercion, and the fabulous “as” keyword:

def b = [ getLine: { "Short book" } ] as Book
assert “Short book” == b.read()

Not only is it less code, but it also protects us from interface changes to getLine! getLine can be changed to take a parameter or throw a new checked exception, and our test would remain unchanged, lessening the maintenance burden of our test case. Very nice.

So, although this is not ideal, it still has benefits over its Java counterpart.

I’m spoiled

Wow, I’m spoiled. Spending the past several years working with Java, Ruby, Erlang, and some others, I’ve grown accustomed to the hoards of free libraries and tools out there just begging to be used. IDEs, code analysis, continuous integration, frameworks, profiling, testing…pretty much anything you could ever want. This rings especially true for Java, since it has been in the limelight for so long. So, I was shocked to find out that there doesn’t appear to be a free comprehensive code coverage tool out there for .NET.

As I’ve mentioned before, I’m writing a test suite for Shotokan Karate of America’s new membership administration system. The application is written in C#. The pace of development has picked up lately, and new code is being released for testing about every couple of weeks. I’m not too involved with the development of the application, so I don’t have much insight as to what has changed from release to release. So, I’ve been looking for a good code coverage tool to show me areas of the application’s code that I may be overlooking in my tests.

I wanted something like Cobertura for Java, which has a rich set of features, and a set of easy to read code coverage reports. But, the only thing I could find that even came close to Cobertura was NCover. Free? Nope. Try $149 a license. Oh…wait, you want the one with the HTML reports? That’s $299.

I’m new to .NET, so naturally this raises a bunch of questions. Is this the status quo in the .NET community? Is everything pay to play? How does this affect the community? If Joe Developer has a library that he thinks others might find useful, does he slap a price tag on it simply because that’s the way things are? How do free open source software projects in .NET (I’m assuming there are some) get started? Does this type of model encourage or discourage community involvement in a project?

Is it just me, or does anybody else think that it sucks to not have these tools freely available to the development community?

I should note that I am a giant tight wad. Don’t believe me? Ask my wife.

A theme at JavaOne - Beyond Java

I noticed a few themes at JavaOne this year. One of the big ones was JavaFX. It had sessions galore, and plenty of stage time at the general sessions. But, another theme I picked up on was the amount of sessions dedicated to non-Java programming languages; perhaps a bit odd considering this was JavaOne.

JRuby and Groovy were all over the place. There was also a session on Scala. These other languages bring new ways of solving problems to the table. In addition to their expressiveness, JRuby and Groovy bring the power of meta programming to the Java world. Scala also brings a more expressive syntax, and the power and flexibility of two programming paradigms: object oriented and functional.

These were the only non-Java programming languages that had sessions associated with them. At the CommunityOne session I attended which was presented by Charlie Nutter, Charlie said that virtually every language out there is capable of running on the JVM, usually via a sub-project. I think this is a very profound statement. It shows that the language implementers or those strongly associated with the language realize the benefits of running on the JVM, and the ability to integrate with the billions of lines of existing Java code out there. Granted that each one of these projects varies in the level it can interact with existing Java code. However, Sun appears to be making a strong effort to work with the implementers of these languages to make integration with Java easier.

I think this is great. I’m sure that Sun realizes how powerful and mature the Java platform has become. And, as a Java programmer, I love the idea of being able to pick a language that best fits the problem I am trying to solve, while still maintaining interoperability with my existing Java code.

The Java language itself appears to be stalling. No widely adopted programming language lives forever. In order for a language to be successful, it must maintain some sort of backward compatibility. Maintaining backward compatibility, while necessary, slows the evolution of the language, and prevents the language from adopting vastly different programming models that may be a better fit for new problems that developers may be facing. Newer languages, or less widely adopted languages, do not face this dilemma and can change more rapidly. I’m also unconvinced of the effectiveness of the whole JCP process. I some situations I feel it is best to have a small group of intelligent individuals at the helm of a project, making all of the decisions. Usually, the more people involved, the longer it takes to get things done.

I think that making the JVM a more attractive environment for non-Java programming languages will only benefit the platform. I think it will also prevent some developers from jumping platforms to use a different programming language that better suits the problem they are trying to solve. I think this is a win for the Java community.

Going to JavaOne!

Late last week I was asked by my manager if I would be interested in going to JavaOne this year. My answer was along the lines of “Hell Yes!”. Well, everything has been officially approved, and I’m now in the middle of booking my hotel and flight to San Francisco. A few of my colleagues here at Orbitz, Matt O’Keefe and Doug Barth, will be presenting on some of the cool event processing work we’ve been doing here at Orbitz. In addition to attending their presentation, I also plan on attending sessions on design, debugging, scripting on the JVM, tools, frameworks, and more. I can’t wait. It’s going to be a great experience!

Java checked exceptions VS runtime exceptions

One of my responsibilities at work is to interview candidates for open technical positions. Given that we are a Java shop, most of our questions naturally revolve around Java, both the language itself and the common open source tools and frameworks that are used by Java developers. An area that we often focus on during the interview is the Java exception hierarchy.

Every Java developer has to deal with exceptions in one way or another. They write code to handle exceptions, throw exceptions, and design APIs that use exceptions in a way that clearly communicates exceptional conditions to their users. Java is one of the few, if not the only programming language (I personally don’t know of any other) to have the concept of checked exceptions. Checked exceptions consist of the java.lang.Exception class and all of its subclasses; except for java.lang.RuntimeException and its subclasses (see below). Checked exceptions are exceptions that the Java compiler forces you to handle by either catching the exception, or re-throwing it. The failure to handle a checked exception results in a compiler error. Every Java developer knows what a checked exception is by the mere fact that they have to deal with them in order to get their code to compile.

Here is a simple example that shows some basic handling of checked exceptions, minus the nitty-gritty details.

// All checked exceptions that a method can throw must be declared in
// the method's throws clause
public void executeSqlStatements(String sqlFileName)
        throws IOException {

   // File operations can throw an IOException.  Listing IOException in
   // the throws clause allows this method to simply re-throw the
   // exception if it is encountered.  No other handling is necessary.
   BufferedReader input = new BufferedReader(new FileReader(sqlFileName));
   String sqlLine = null;
   try {
      while ((sqlLine = input.readLine()) != null) {
         // Executes a DB query, could throw an SQLException (checked)
         executeSql(sqlLine);

         // Could throw an InterruptedException (checked)
         Thread.sleep(1000);
      } 

   // SQLException and InterruptedException are not listed in the throws
   // clause, so they must be caught and handled here.
   } catch (SQLException e) {
      // IllegalArgumentException is a runtime exception, not required
      // to be listed in the throws clause (although you should for
      // documentation purposes)
      throw new IllegalArgumentException("Error executing SQL: " +
            sqlLine, e);

   } catch (InterruptedException e) {
      // Log and swallow
      logger.error("Unable to sleep!", e);

   } finally {
      input.close();
   }
}

What continuously surprises me is the number of Java developers I interview that have no idea what a runtime exception is or how it can be used. Runtime exceptions serve the same purpose as checked exceptions; to communicate exceptional conditions (unexpected failures, etc) to the user. They can be thrown and caught just like checked exceptions. However, handling runtime exceptions is not enforced by the compiler. This is how exceptions work in other programming languages. I was first introduced to the usefulness of runtime exceptions in Java while reading Professional J2EE Design and Development, by Rod Jonson, the creator of the Spring Framework. In that book, Rod questioned the over use of checked exceptions in Java. Rod pointed out that using a checked exception forces the caller of a method to handle that exception, even if they do not know how to handle it. Often times, developers will end up catching the checked exception, only to re-throw it (or another exception). If the code throws a new exception that does not wrap the original exception, the stack trace of the original exception, priceless for debugging, is lost. And, I’m sure we’ve all seen the dreaded “Log and Swallow” anti-pattern when the code doesn’t know what to do with an exception.

What’s the point in catching an exception if nothing can be done about it, or it has to be handled by another layer? You simply have to write a bunch of boiler plate code to catch and re-throw the exception until it gets to somebody that can handle it. Or, you have to pollute the throws clause of your method signature with a bunch of exceptions that your method itself does not throw, or with exceptions that may not be relevant to what that particular method is supposed to do. This is where runtime exceptions save the day. Since runtime exceptions can simply “bubble up” the stack, to either somebody who can handle the exception or to a catch-all, you only have to deal with the exception in one place. This reduces the amount of code you have to write, and reduces of number of places a bug can creep in. It also saves methods from having to catch or re-throw exceptions that they can’t recover from.

I think checked exceptions do still serve a purpose. I believe checked exceptions should be thrown when the caller is expected to handle the exception. For example, imagine you have an object that only does one thing: write data to a database.

public class DataWriter {

   public void updateRow(MyDataObject theData)
         throws DatabaseConnectionException, ConcurrentModificationException {
      // Make the DB call to update the row
   }
}

Let’s say it throws two exceptions, DatabaseConnectionException and ConcurrentModificationException. Of these two, I’d say that the ConcurrentModificationException could be handled by the caller. Maybe the caller will read the row that was updated, and present the user with their update and the concurrent update, asking her to either merge or overwrite the data. Maybe the calling code can handle this automatically. Either way, it’s recoverable. So, I might make this a checked exception, forcing the caller to handle it. However, the DatabaseConnectionException is a bit trickier. The caller of updateRow() may not know how to initialize a new database connection, or how to clean up an abandoned connection. I would probably make this exception a runtime exception, and let it propagate up to the top of the stack. This way, we could either show the user a general error message saying that the operation could not be completed (asking them to retry) or try to clean up the first attempt and re-try the operation for a second time automatically. The beauty about this is that this exception can be caught and handled, just like a checked exception, at any layer in the stack. So the layer that knows how to recover from the exception can catch it, and take the necessary action. All of this without having to catch and re-throw the exception once and without having to pollute our method signatures with throws DatabaseConnectionException.

One of the common complaints about using runtime exceptions is that since they do not have to be declared in the throws clause of the method that throws them, like checked exceptions do, it is often unclear what exceptions may be thrown by a method. But, just because they don’t have to be listed in the throws clause doesn’t mean that they can’t be. I believe that every method should list, in its throws clause, what exceptions it throws (checked and runtime). This way it is clear to the user what to expect out of the method. Adequate JavaDoc explaining why each of the exceptions may be thrown is also very useful. If your exception hierarchy is designed well, and you have a good separation of layers in your architecture, no individual method’s throws clause should become too verbose.

It is also important to use some form of catch-all at the top of your stack to prevent any runtime exceptions from slipping out and crashing the VM. I’ve found it helpful to properly log any exceptions caught in the catch-all, so that code can be added to handle or wrap them in a more appropriate place.

The Spring Framework uses runtime exceptions extensively. And at Orbitz, we’ve been exclusively using runtime exceptions for some time now. I think they make the code easier to read, maintain, extend, and comprehend. I can’t even imagine going back to using checked exceptions exclusively.