Staying exceptionally WET

how-to
Jan 18, 20093 mins

The question of how to test for exceptions comes up quite frequently. While there’s more than one way to skin a cat, so to speak, man, I’ve found that documenting intent is often more helpful in quickly conveying behavior.

Case in point, with the advent of JUnit 4’s expected attribute of the @Test annotation, it’s quite easy to concisely specify which exception a given test case should throw.

For example, below is JUnit 4’s exception handling shortcut in action:

<pre class="prettyprint"><code>@Test(expected=RuntimeException.class)
public void testComputeIrr() {
  double [] cashflow = {100.0, 90.0, 80.0, 70.0};
  FinancialMath.computeIrr(cashflow, 0.01);
}

In this case, the testComputeIrr method should throw a RuntimeException (due to the lack of a negative cash flow in position 0). Using this technique, however, does impair the intent slightly of the code under test as the inherent compactness of the attribute syntax requires some expanded thinking.

Antony Marcano recently wrote a hip blog entry entitled “Writing tests for Excepted Exceptions – a slightly different way…” in which he demonstrates a more expressive technique for verifying exceptional circumstances. His preferred style of exception verification also happens to be mine; that is, utilize a try/catch phrase, which wholly expresses the test (WET) resulting in a clearer picture of expected (or non expected behavior).

For example, WET-ing the first example would yield a more effusive test, but it serves as clearer, more hip documentation:

<pre class="prettyprint"><code>@Test
public void testComputeIRR(){
 try{
  double [] cashflow = {100.0, 90.0, 80.0, 70.0};
  FinancialMath.computeIrr(cashflow, 0.01);
  fail("computeIRR didn't throw an exception");
}catch(Throwable thr){
  assertTrue("exception type should be RuntimeException",
     thr instanceof RuntimeException);
 }
}

Incidentally, easyb also supports a shorthand mechanism for verifying exceptions — for instance, I can rewrite the first JUnit example as:

<pre class="prettyprint"><code>
given "a cash flow with all positive values", {
 cashflow = [100, 90, 80, 70] as double[]
}
then "the IRR computation should throw a RuntimeException", {
 ensureThrows(RuntimeException){
  FinancialMath.computeIrr(cashflow, 0.01)
 }
}

While easyb’s expressiveness largely meets the notion of WET (that is, the then phrase is providing additional context to the code) you can, of course, be WETer and avoid the ensureThrows clause like so

<pre class="prettyprint"><code>given "a cash flow with all positive values", {
 cashflow = [100, 90, 80, 70] as double[]
}
then "the IRR computation should throw a RuntimeException", {
 try{
  FinancialMath.computeIrr(cashflow, 0.01)
 }catch(e){
   e.shouldBeA RuntimeException
   e.getMessage().shouldBe "Only positive cashflows"
 }
}

In the code above, I’m verifying the same behavior, albeit in a more demonstrative manner, plus, I’m able to ensure the exception is providing a specific message. You can, by the way, also achieve the same result using the 2nd more expressive JUnit example.

Documenting intent is often more helpful in quickly conveying hip behavior as it serves to clearly express the tale or test or story (wholly expressing the story doesn’t work so well as an acronym though). Applying DRY principles might yield fewer lines of code (and I’m a big fan of less code) but in some cases it pays to be copasetically WET, baby.

Want to learn more about Groovy and Grails? Then sign up for ThirstyHead’s Jump into Groovy and Grails course!

Think easyb is the coolest thing since sliced bread? Then come to my

BDD with easyb

course too!

andrew_glover

When Andrew Glover isn't listening to “Funkytown” or “Le Freak” he enjoys speaking on the No Fluff Just Stuff Tour. He also writes articles for multiple online publications including IBM's developerWorks and O'Reilly’s ONJava and ONLamp portals. Andrew is also the co-author of Java Testing Patterns, which was published by Wiley in September 2004; Addison-Wesley’s Continuous Integration; and Manning’s Groovy in Action.

More from this author