DaedTech

Stories about Software

By

JUnit for C# 3 – Mocks and Other Niceties

Edit: It occurs to me that the name here was kind of an oops. If you’re here to see how I use JUnit while developing in C#, you’re probably going to be disappointed. I meant to title this “JUnit for C# Developers 3”, but made a rather comical omission. My apologies.

As I go along with this series of posts, I’ve come to a decision. My plan is to get my new, open source home automation server working at the level of functionality my old, struts-based one currently works. I think I’m going to muddle through TDD and posting my adventures for as long as that takes, and then I’ll probably add it to github to see if anyone wants to pull, and move on to other posting topics (like my practical design patterns series that I’ve been a little slow on lately). But, for now, I’ll keep on with these.

Goals for Today

Since my last two posts were more of a whim, I decided to get organized a little now that I’m in the swing of it. So, my goals for today’s post are the following:

  1. Find out whether or not Java now supports optional parameters.
  2. Figure out how to assert that a method throws an exception
  3. Figure out how to run a single unit test only
  4. Get setup with a mocking framework.

I figure that’s a bite-sized chunk for an hour or two, so let’s get started.

Actual Work

So, first up is Java and default parameters. The answer there seems to be a resounding “no” (it’s acquired foreach and instanceof, so I figured it was worth a shot). I saw this stackoverflow post, and upvoted the question while I was at it, but the answer seemed to be no. Given that the post was somewhat outdated, I checked around in some other places as well with the same findings. Bummer. The reason I wanted to find this out for my TDD is that I’ve adopted a pattern of doing something like this for my tests:

        /*
	 * This is here for TDD to stop me from needing to change every test
	 * if I decide to inject a xtor param
	 */
	private static LightController buildTarget(LightManipulationService service = null) {
		LightManipulationService myService = service != null ? service : new MockLightManipulationService();
		return new LightController(myService);
	}

Basically, instead of directly instantiating the class under test (CUT), I delegate that responsibility to this builder method. That way, if I decide to add a constructor parameter to the CUT, I don’t have to bother with the tiresome chore of updating all of my tests. And, adding a constructor parameter is a rather frequent occurrence for me when doing TDD.

But, it turns out that I’ll have to settle for the noisiness of a method overload to accomplish this. Perhaps its the purist in me, but I think default parameters in C# (and other languages) are a much more elegant solution to this problem than method overloads. I hate boilerplate code — it’s just more places you have to maintain and more places mistakes could be made. So, first goal accomplished, if not in a satisfying way. More on the builder and supplying an interface to the controller later.

Next up, I want to add a constructor parameter to my controller, as you may have intuited. The purpose of this light controller is to allow a user to turn lights in my house on and off with a RESTful URL scheme. The actual mechanics of lights on/off is accomplished via a shell command that invokes a driver my server is running. However, it is wildly inappropriate for a presentation layer controller to know the details of how that works, so I’m abstracting out a conceptual service:

public interface LightManipulationService {

	/**
	 * Turns the light in question on or off
	 * @param light - the light to toggle
	 * @param isOn - the setting (true for on, false for off)
	 * @return whether or not the operation was successful
	 */
	Boolean toggleLight(Light light, Boolean isOn);
	
	/**
	 * Change the brightness of a light
	 * @param light - the light to modify
	 * @param brightnessChange - the brightness change (positive for brighter, negative for dimmer)
	 * @return whether or not the operation succeeded
	 */
	Boolean ChangeBrightness(Light light, int brightnessChange);
}

“Light” is a POJO that I made to encapsulate properties for the room containing the light and the name of the light. The controller will operate by parsing the URL For the room and light parameters and then passing a corresponding light object to the service, which will take care of the actual light operations in a nod to the single responsibility principle.

Now, I want to inject an implementation of this interface into my controller and, furthermore, I want to throw an exception if a client injects null. After all, the controller for lights can’t operate in any meaningful way if it doesn’t have a service that actually does things to the lights. And this is where goal number (2) comes in. It turns out that testing for a thrown exception is pretty straightforward:

@Test(expected=IllegalArgumentException.class)
	public void constructor_Throws_Exception_On_Null_Service_Argument() {
		new LightController((LightManipulationService)null);
	}

That’s all there is to it. As an aside, I’m pretty impressed with Eclipse’s ability to take action during my TDD. For instance, when I instantiated the controller this way, I got a red won’t-compile squiggly as one would expect. As an option for fixing, I was allowed to declare a new constructor, ala CodeRush in Visual Studio (truth be told, VS may offer this too, but I’ve been using CodeRush for so long I don’t remember).

Now, my next goal was figuring out how to run an individual test, mostly for my own edification. Back to stackoverflow where I upvoted another question and answer:

In the package explorer unfold the class. It should show you all methods. Right click on the one method you want to run, then select Run As -> JUnit from the context menu (just tested with Eclipse 3.4.1). Also selecting “Run” on a single entry in the JUnit-results view to re-run a test works in the same way.

Sure enough, that did it. I can run it by right clicking the method or by highlighting it and using Ctrl-Shift-X, T. This is good enough for now, though what I’d really like is the ability that CodeRush and Visual Studio both confer to run a test with a key shortcut with my cursor inside the test. Perhaps that’ll be a goal for next time.

Now, for the meat of this post, a mocking framework. After getting that last test to pass, I now have a problem in that my code won’t compile, since I have another test that needs to inject something into the controller to get it to pass. For a mocking framework, I decided on Mockito. I chose this framework based entirely on “what did James Shore use in Let’s Play TDD”. My philosophy, generally speaking, is “get it working, optimize later”, so picking any framework and using it is better than deliberating long and hard. And, if a guy like James is using it, it’s probably worthwhile.

Installation was easy. I downloaded the jar from the download site and created a directory in my eclipse folder called “externaljars” where I placed it. I have no idea if this is a good practice or not, but a tutorial I looked at suggested creating a C:\mockito directory and I really prefer not to create clutter in root or anywhere else. Until someone tells me why not to, I’ll just stick these things in a sub-directory of Eclipse that I include in my build path.

So, next, I included this directory in my build path. 🙂 From there, I just added the mockito import and defined an overload that I mentioned while fulfilling goal (1), and I had this CUT:

@Controller
@RequestMapping("/light")
public class LightController {

	public LightController(LightManipulationService lightManipulationService) {
		if(lightManipulationService == null) throw new IllegalArgumentException("lightManipulationService");
	}

	@RequestMapping("/light")
	public ModelAndView light() {
		return new ModelAndView();
	}
}

And 4 passing tests:


package com.daedtech.daedalustest.controller;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import org.junit.Test;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.daedtech.daedalus.controller.LightController;
import com.daedtech.daedalus.services.LightManipulationService;

public class LightControllerTest {

	private static LightController buildTarget() {
		return buildTarget(null);
	}
	
	private static LightController buildTarget(LightManipulationService service) {
		LightManipulationService myService = service != null ? service : mock(LightManipulationService.class);
		return new LightController(myService);
	}
	
	@Test(expected=IllegalArgumentException.class)
	public void constructor_Throws_Exception_On_Null_Service_Argument() {
		new LightController((LightManipulationService)null);
	}
	
	@Test
	public void light_With_No_Parameters_Returns_Instance_Of_Model_And_View() {
		
		LightController myController = buildTarget();
		
		Assert.isInstanceOf(ModelAndView.class, myController.light());		
		
	}
	
	@Test
	public void light_Is_Decorated_With_RequestMapping_Annotation() throws NoSuchMethodException, SecurityException {
		
		Class myClass = LightController.class;
		Method myMethod = myClass.getMethod("light");
		Annotation[] myAnnotations = myMethod.getDeclaredAnnotations();
		
		Assert.isTrue(myAnnotations[0] instanceof RequestMapping);
	}
	
	@Test
	public void light_RequestMapping_Has_Parameter_Light() throws NoSuchMethodException, SecurityException {
		
		Class myClass = LightController.class;
		Method myMethod = myClass.getMethod("light");
		Annotation[] myAnnotations = myMethod.getDeclaredAnnotations();
		
		String myAnnotationParameter = ((RequestMapping)myAnnotations[0]).value()[0];
		
		assertEquals("/light", myAnnotationParameter);
	}
}

Now, we’re getting somewhere! This class is going to be functional pretty soon!