Stories about Software


JUnit for C# Developers 4 – BDD, Mocks, and Matchers

This is yet another in my series of posts on using JUnit from the perspective of a C# developer.


Today, I have the following goals in my quest for JUnit TDD proficiency.

  1. Use a BDD-style testing scheme with nested classes.
  2. Use mocking framework to verify method call
  3. Use mocking framework to verify method call with parameters.

Getting to Work

First up, I’d like to see how to employ the test organization scheme described in this post by Phil Haack. The idea is that rather than simply having a test class per class under test, you’ll have a test class and nest within it a sub class for each method in the class under test.

Under Drew’s system, I’ll have a corresponding top level class, with two embedded classes, one for each method. In each class, I’ll have a series of tests for that method.

When you look at this in the test-runner, you see the same descriptive name, but the tests are better organized and can be run at another level of granularity. I’ve come to favor this style when I’m writing code in C#, and I thought I’d see how well it ported to JUnit. As it turns out, the test runner ignores the tests if you simply stick them in sub-classes. I poked around a little and discovered a post by Joshua Lockwood where he had the same idea and found a solution. I tried this out and it got me almost all the way there. I did need one minor tweak, however. (His post was written in 2008, so plenty may have changed in the interim). The “Enclosed” class that he uses required me to import “org.junit.experimental.runners.Enclosed”. By adding this line, I was off and running (though I did have to manually add the import as the IDE didn’t seem to find it):

Notice the class annotation and the new static nested classes. These nested classes do have to be public and static for the scheme to work. In addition, it seems that once you use the “Run With Enclosed” paradigm, all tests must be in enclosed static classes to run. If you had some defined in the test class itself, the test runner would ignore them.

So, now that organization is better, onto more concrete matters. I now want to use my mocking framework to verify that a method was called. I want to add a method to the controller that takes a room name, a light name, and a text command (“on” or “off”) and issues a command to the service based on that. Using Mockito, I wrote the following test:

The statement at the end is the equivalent of the “assert” here. I start out by building a mock using Mockito, and then I hand it to my overloaded builder, which injects it into my CUT. I perform (or will perform, since this method isn’t yet defined) an operation on the controller, and then I want to verify that performing that method resulted in a call to the interface’s toggleLight() method. The “any” parameters are known as “matchers” and they can be used in tests not just to see if a method on a collaborator was called, but with what kinds of parameters.

In the C# world, I use Moq and am a big fan of it. If you use this in C#, this whole paradigm should look pretty familiar. We create a mock, inject it, manipulate it, and verify it. Verify here is a static method that takes the mock as an argument, rather than an instance method of the mock, and mock creation is the same, but beyond that, these constructs look very similar, right down to the static “any()” methods for argument matching.

My final goal was to get to the point of using the aforementioned matchers to make sure the service methods were being invoked as I envisioned. To make the last test pass, I wrote the following “simplest possible” TDD code:

Since the unit test allowed for any Light object and any boolean to be the parameters, I opted for null and false, respectively. Doesn’t get much simpler than that. To advance my goals a bit, I know that when the command string passed to the method is “on”, I want to call the service with boolean parameter true. So, let’s see how that test would look:

It’s a nearly identical test, but this time around, notice that I’ve traded “anyBoolean()” for “eq(true)”. Now this test will only pass if the toggleLight() method calls the service with boolean true. the eq() static method returns a matcher for a specific value. Getting all tests to pass is pretty straightforward here:

Obviously, this method is pretty obtuse and needs some work, but I’ll get to that in the “off” command parameter case. The beauty of TDD is that you go from obtuse to rigor and accuracy by adding only the complexity you need in order to satisfy the next requirement. So, to recap, here is the current state of affairs of the controller:

and the test class: