TDD

Materials from HDC09 – Testing With Mocks Talk

Below is a link to download the Testing With Mocks lightning round talk that I gave at the Heartland Developers Conference this last week.

In order to get the samples to run you will need to have TypeMock Isolator installed. If you do not own a license you can download an evaluation for free here.

The download includes full buildable source and the presentation.

Download: TestingWithMocks_HDC09.zip (~15MB)

TypeMock 5.3.5 – WasCalledWithArguments

I normally do not blog bile by reposting another sites news, but this news is rather importnat in regards to TDD with Isolator.

I use Rhino Mocks 80% of the time for mocking, but that last 20% is Isolator. Why 20% – this is the real tough stuff to test. SharePoint, Silverlight, Tightly Coupled Legacy code (that I do not have source to), etc. In Rhino I’ve been able to assert with arguments for quite awhile now. Isolator did not fully support this, they do now!

See this release notice here: http://blog.typemock.com/2009/09/typemock-isolator-535-is-out.html

What does this mean? It means that you can assert whether or not arguments made to a particular mocked object were what you expect them to be. Perpaps. If they are not, then your test should fail. If your method performs various manipulations through various other calls, you can ensure that through the execution stack of your app, your calls are being made with what you expect them to be. If not, tests fail.

 

Fail fast is the name of the game and Isolator just stepped up theirs. Good stuff guys.

Unit Testing you Container Dependencies

When developing with an inversion of control container (I use Windsor) its sometimes difficult to detect if your instances in your container are creatable or not. A lot of times this is determined when you run the app, you’ll get an exception informing you that your object does not have all of its dependencies fulfilled.

Therefore…the real question is …

Did you register everything in the container? Or did you forget something?

I know from personal experience I’ve forgotten to register components many times so I started relying on unit tests to catch me when I failed.

 

How to Test that you Registrations are Creatable

This simple unit test will assert that your components are creatable.

[Test]
public void All_components_in_container_should_be_creatable()
{
	var kernel = new DefaultKernel();
	var handlers = new List<IHandler>();

	kernel.ComponentRegistered += (name, handler) => handlers.Add(handler);

	// Used in our Global.asax on App Start to register our components.
	var app = new Application();

	// Same call that we make in Global asax
	app.RegisterComponents(kernel); 

	// If the container (kernel) cannot resolve the instance
	// an exception will be thrown and the test will fail
	handlers.ForEach(handler =>
						 {
							 if (handler.CurrentState == HandlerState.WaitingDependency)
								 kernel.Resolve(handler.ComponentModel.Name, handler.Service);
						 });
}

Code Explained

Background: In all of the apps I write now I have an Application.cs file. This file is responsible for bootstrapping the container and everything else the app needs to run (Logging, Diagnostics, Facilities, etc). Inside of this Application.cs file I have a “RegisterComponents” call which registers all of the required components in the container.

Therefore, the code above creates a new container (kernel) and then we create a list of IHandler’s. An IHandler is an interface in Windsor Container (the container I’m using here) that manages component state and coordinates its creation and destruction.

The next line is a sweet little lambda expression that says …

“When a component is registered in the container, I want to add its handler to a list of Handlers”

Which of course, is the list we just created.

The next few lines set up the application and register the components.

The last call in the test is where the magic happens.

We iterate over the list of handlers and check their CurrentState property. If the state of the component is still waiting for a dependency to be resolved (perhaps it has something injected into the constructor) we will then try to resolve the component with the name of the component and service type. If it can be resolved, it will resolve and nothing will happen (which is good). However… if the container _cannot_ resolve the component, an exception of type Castle.MicroKernel.Handler.HandlerException will be thrown.

The exception looks like this:

Castle.MicroKernel.Handlers.HandlerException: Can’t create component ‘Foo.Bar.OrderRepository’ as it has dependencies to be satisfied. 
‘Foo.Bar.OrderRepository is waiting for the following dependencies: 
Keys (components with specific keys)

- dataStore which was not registered. 
- dataMapper which was not registered.
 

As we can see above, the “Foo.Bar.OrderRepository” could not be resolved as the container could not find the “dataStore” parameter, or the “dataMapper” attribute.

At this point your test will fail and you’ll see that you have an issue with your container set up. Investigate, fix and retest!

Finding App_Data Programmatically

While writing some code I needed to be able to access the the App_Data directory in my ASPNET MVC app. Doing this usually involves a Server.MapPath, but this wont work for my unit test.

Here’s how you can get around it:

 

var appDataPath = (string)AppDomain.CurrentDomain.GetData("DataDirectory") ?? AppDomain.CurrentDomain.SetupInformation.ApplicationBase;

 

Now I have my data directory for the test as well as during execution of the ASPNET MVC app.

During unit test execution it will be in testing directory while at runtime it will be in the ASPNET App_Data directory.

Featured in the Spaghetti Code Podcast

I was recently interviewed on the Spaghetti Code Podcast, hosted by Microsoft’s Jeff Brand.

Jeff and I talked about Mocking and how it relates to the development process, testing process and your day to day coding.

You can download the files from the SlickThought website here or from ITunes here.

* I’m not sure if ITunes has updated yet, but it should be up there soon.