One of the guiding principles in the design of the new ASP.NET MVC Framework
is enabling TDD (Test Driven Development) when building a web
application. If you want to follow along, this post makes use of ASP.NET
MVC CodePlex Preview 4 which you’ll need to install from CodePlex. I’ll try and keep this post up to date with the latest releases, but it may take me time to get around to it.
This post will provide a somewhat detailed walk-through of building a web application in a Test Driven manner while also demonstrating one way to integrate a Dependency Injection (DI) Framework into an ASP.NET MVC app. At the very end, you can download the code.
I chose StructureMap 2.0 for the DI framework simply because I’m familiar with it and it requires very little code and configuration. If you’re interested in an example using Spring.NET, check out Fredrik Normen’s post. I’ll try and post code examples in the future using Castle Windsor and ObjectBuilder.
At this point, you should see the following unit test project selection dialog.
In a default installation, only the Visual Studio Unit Test project option is available. But MbUnit, xUnit.NET and others have installers available to get their test frameworks in this dialog.
As you might guess, I’ll start off building the canonical blog demo. I am going to start without using a database. We can always add that in later.
The first thing I want to do is add a few classes to the main project. I won’t add any implementation yet, I just want something to compile against. I’m going to add the following:
At this point, I want to implement just enough code so we can write a test. First, I define my repository interface.
Ok, so that’s the GREEN part of the TDD lifecycle and a very very simple demo of TDD. Let’s move to the REFACTOR stage and start applying Dependency Injection.
At this point, I’m not sure how I’m going to store my blog posts. Will I use SQL? XML? Stone Tablet?
Dunno. Don’t care... yet.
We can delay that decision till the last responsible moment. For now, I’ll create a repository abstraction to represent how I will store and retrieve blog posts in the form of an
This is the dependency part of Dependency Injection. My controller now has a dependency on
Here’s the change to my

Well of course it errors out! By default, ASP.NET MVC requires that controllers have a public parameter-less constructor so that it can create an instance of the controller. But our constructor requires an instance of
StructureMap (or DI framework of your choice) to the rescue!
Note: Make sure to download and reference the StructureMap.dll assembly if you’re following along. I've included the assembly in the source code at the end of this post.
The first step I’m going to do is create a StructureMap.config file and add it to the root of my application. Here are the contents of the file.
For example, in the second
Well if that’s true, we better then create that class. Normally, I would use a
Note: This is where I would normally write tests for
Excellent! Despite the Yellow Screen of Death here, this is a good sign. We know our dependency is getting injected because this is a different error message than we were getting before. This one in particular is informing us that we haven’t created a view for this action. So we need to create a view.
Sorry! Out of scope. Not in the spec.
I leave it as an exercise for the reader to create a view for the page, or you can look at the silly simple one included in the source download.
Although this example was a ridiculously simple application, the principle applies in building a larger app. Just take the techniques here and rinse, recycle, repeat your way to TDD nirvana.
To see the result of all this, download the source code.
This post will provide a somewhat detailed walk-through of building a web application in a Test Driven manner while also demonstrating one way to integrate a Dependency Injection (DI) Framework into an ASP.NET MVC app. At the very end, you can download the code.
I chose StructureMap 2.0 for the DI framework simply because I’m familiar with it and it requires very little code and configuration. If you’re interested in an example using Spring.NET, check out Fredrik Normen’s post. I’ll try and post code examples in the future using Castle Windsor and ObjectBuilder.
Start Me Up! with apologies to The Rolling Stones
Once the CTP is released and you have it installed, open Visual Studio 2008 and select the File | New Project menu item. In the dialog, select the ASP.NET MVC Web Application project template.
At this point, you should see the following unit test project selection dialog.

In a default installation, only the Visual Studio Unit Test project option is available. But MbUnit, xUnit.NET and others have installers available to get their test frameworks in this dialog.
As you might guess, I’ll start off building the canonical blog demo. I am going to start without using a database. We can always add that in later.
The first thing I want to do is add a few classes to the main project. I won’t add any implementation yet, I just want something to compile against. I’m going to add the following:
- BlogController.cs to the Controllers directory
- IPostRepository.cs to the Models directory
- Post.cs to the Models directory
- BlogControllerTests to the MvcApplicationTest project.

At this point, I want to implement just enough code so we can write a test. First, I define my repository interface.
using System; using System.Collections.Generic; namespace MvcApplication.Models { public interface IPostRepository { void Create(Post post); IList<Post> ListRecentPosts(int retrievalCount); } }
Not much of a blog post repository, but it’ll do for
this demo. When you’re ready to write the next great blog engine, you
can revisit this and add more methods.
Also, I’m going to leave the Post class empty for the
time being. We can implement that later. Let’s implement the blog
controller next.
using System; using System.Web.Mvc; namespace MvcApplication.Controllers { public class BlogController : Controller { public ActionResult Recent() { throw new NotImplementedException("Wait! Gotta write a test first!"); } } }
Ok, we better stop here. We’ve gone far enough without
writing a unit test. After all, I’m supposed to be demonstrating TDD.
Let’s write a test.
Let’s Get Test Started, In Here. with apologies to the Black Eyed Peas
Starting with the simplest test possible, I’ll make sure that theRecent
action does not specify a view name because I want the default behavior
to apply (this snippet assumes you’ve imported all the necessary
namespaces).[TestClass] public class BlogControllerTests { [TestMethod] public void RecentActionUsesConventionToChooseView() { //Arrange var controller = new BlogController(); //Act var result = controller.Recent() as ViewResult; //Assert Assert.IsTrue(String.IsNullOrEmpty(result.ViewName)); } }
When I run this test, the test fails.

This is what we expect, after all, we haven’t yet implemented the
Recent
method. This is the RED part of the RED, GREEN, REFACTOR rhythm of TDD.
Let’s go and implement that method.
public ActionResult Recent() { //Note we haven’t yet created a view return View(); }
Notice that at this point, we’re focusing on the
behavior of our app first rather than focusing on the UI first. This is a
stylistic difference between ASP.NET MVC and ASP.NET WebForms. Neither
one is necessarily better than the other. Just a difference in approach
and style.
Now when I run the unit test, it passes.
Ok, so that’s the GREEN part of the TDD lifecycle and a very very simple demo of TDD. Let’s move to the REFACTOR stage and start applying Dependency Injection.
It’s Refactor Time! with apologies to the reader for stretching this theme too far
In order to obtain the recent blog posts, I want to provide my blog controller with a “service” instance it can request those posts from.At this point, I’m not sure how I’m going to store my blog posts. Will I use SQL? XML? Stone Tablet?
Dunno. Don’t care... yet.
We can delay that decision till the last responsible moment. For now, I’ll create a repository abstraction to represent how I will store and retrieve blog posts in the form of an
IPostRepository
interface. We’ll update the blog controller to accept an instance of this interface in its constructor.This is the dependency part of Dependency Injection. My controller now has a dependency on
IPostRepository
. The injection
part refers to the mechanism you use to pass that dependency to the
dependent class as opposed to having the class create that instance
directly and thus binding the class to a specific implementation of that
interface.Here’s the change to my
BlogController
class.public class BlogController : Controller { IPostRepository repository; public BlogController(IPostRepository repository) { this.repository = repository; } public ActionResult Recent() { //Note we haven’t yet created a view return View(); } }
Great. Notice I haven’t changed
Recent
yet. I need to write another test first. This will make sure that we pass the proper data to the view.
Note: If you're following along,
you’ll notice that the first test we wrote won't compile. Comment it out
for now. We can fix it later.
I’m going to use a mock framework, so before I write this test, I need to reference Moq.dll in my test project, downloaded from the MoQ downloads page.
Note: I’ve included this assembly in the example project at the end of this post.
Here’s the new test.
[TestMethod] public void BlogControllerPassesCorrectViewData() { //Arrange var posts = new List<Post>(); posts.Add(new Post()); posts.Add(new Post()); var repository = new Mock<IPostRepository>(); repository.Expect(r => r.ListRecentPosts(It.IsAny<int>())).Returns(posts); //Act BlogController controller = new BlogController(repository.Object); var result = controller.Recent() as ViewResult; //Assert var model = result.ViewData.Model as IList<Post>; Assert.AreEqual(2, model.Count); }
What this test is doing is dynamically stubbing out an implementation of the
IPostRepository
interface. We then tell it that no matter what argument is passed to ListRecentPosts
, return two posts. We can then pass that stub to our controller.
Note: We haven’t yet needed to
implement this interface. We don’t need to yet. We’re interested in
isolating our test to only test the logic in the action method, so we
fake out the interface for the time being.
At this point, the test fails as we expect. We need to refactor
Recent
to do the right thing now. public ActionResult Recent() { IList<Post> posts = repository.ListRecentPosts(10); //Doh! Magic Number! return View(posts); }
Now when I run my test, it passes!
Inject That Dependency
But we’re not done yet. When I load up a browser and try to navigate to this controller action (on my machine, http://localhost:64701/blog/recent/), I get the following error page.
Well of course it errors out! By default, ASP.NET MVC requires that controllers have a public parameter-less constructor so that it can create an instance of the controller. But our constructor requires an instance of
IPostRepository
. We need someone, anyone, to pass such an instance to our controller.StructureMap (or DI framework of your choice) to the rescue!
Note: Make sure to download and reference the StructureMap.dll assembly if you’re following along. I've included the assembly in the source code at the end of this post.
The first step I’m going to do is create a StructureMap.config file and add it to the root of my application. Here are the contents of the file.
<?xml version="1.0" encoding="utf-8" ?> <StructureMap> <Assembly Name="MvcApplication" /> <Assembly Name="System.Web.Mvc , Version=1.0.0.0 , Culture=neutral , PublicKeyToken=31bf3856ad364e35" /> <PluginFamily Type="System.Web.Mvc.IController" Assembly="System.Web.Mvc , Version=1.0.0.0 , Culture=neutral , PublicKeyToken=31bf3856ad364e35"> <Plugin Type="MvcApplication.Controllers.BlogController" ConcreteKey="blog" Assembly="MvcApplication" /> </PluginFamily> <PluginFamily Type="MvcApplication.Models.IPostRepository" Assembly="MvcApplication" DefaultKey="InMemory"> <Plugin Assembly="MvcApplication" Type="MvcApplication.Models.InMemoryPostRepository" ConcreteKey="InMemory" /> </PluginFamily> </StructureMap>
I don’t want to get bogged down in describing this file in too much detail. If you want a deeper understanding, check out the StructureMap documentation.
The bare minimum you need to know is that each PluginFamily
node describes an interface type and a key for that type. A Plugin
node describes a concrete type that will be used when an instance of the family type needs to be created by the framework.For example, in the second
PluginFamily
node, the interface type is IPostRepository
which we defined. The concrete type is InMemoryPostRepository
. So anytime we use StructureMap to construct an instance of a type that has a dependency on IPostRepository
, StructureMap will pass in an instance of InMemoryPostRepository
.Well if that’s true, we better then create that class. Normally, I would use a
SqlPostRepository
.
But for purposes of this demo, we’ll store blog posts in memory using a
static collection. We can always implement the SQL version later.Note: This is where I would normally write tests for
InMemoryPostRepository
but this post is already long enough, right? Don’t worry, I included unit tests in the downloadable code sample.public class InMemoryPostRepository : IPostRepository { //simulates database storage private static IList<Post> posts = new List<Post>(); public void Create(Post post) { posts.Add(post); } public System.Collections.Generic.IList<Post> ListRecentPosts(int retrievalCount) { if (retrievalCount < 0) throw new ArgumentOutOfRangeException("retrievalCount" , "Let’s be positive, ok?"); IList<Post> recent = new List<Post>(); int recentIndex = posts.Count - 1; for (int i = 0; i < retrievalCount; i++) { if (recentIndex < 0) break; recent.Add(posts[recentIndex--]); } return recent; } public static void Clear() { posts.Clear(); } }
Quick, We Need A Factory
We’re almost done. We now need to hook up StructureMap to ASP.NET MVC by writing implementingIControllerFactory
.
The controller factory is responsible for creating controller
instances. We can replace the built in logic with our own factory.public class StructureMapControllerFactory : DefaultControllerFactory { protected override IController CreateController(RequestContext requestContext, string controllerName) { try { string key = controllerName.ToLowerInvariant(); return ObjectFactory.GetNamedInstance<IController>(key); } catch (StructureMapException) { //Use the default logic. return base.CreateController(requestContext, controllerName); } } }
Finally, we wire it all up together by adding the following method call within the
Application_Start
method in Global.asax.cs.protected void Application_Start() { ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory()); RegisterRoutes(RouteTable.Routes); }
And we’re done! Now that we have hooked up the
dependency injection framework into our application, we can revisit our
site in the browser (after compiling) and we get...

Excellent! Despite the Yellow Screen of Death here, this is a good sign. We know our dependency is getting injected because this is a different error message than we were getting before. This one in particular is informing us that we haven’t created a view for this action. So we need to create a view.
Sorry! Out of scope. Not in the spec.
I leave it as an exercise for the reader to create a view for the page, or you can look at the silly simple one included in the source download.
Although this example was a ridiculously simple application, the principle applies in building a larger app. Just take the techniques here and rinse, recycle, repeat your way to TDD nirvana.
To see the result of all this, download the source code.
0 comments:
Post a Comment