Testing the Untestable with Delegate Injection

My ASP.NET skills may be a bit rusty, but that’s not stopping me from working on a side project in ASP.NET MVC. While it has made significant strides in the 4.0 release, code like this demonstrates that ASP.NET still has a long way to go to improve testability.

public class AccountController : Controller
{
    ITwitterService _twitter;

    //constructor dependency injection
    public AccountController(ITwitterService twitterService)
    {
        _twitter = twitterService;
    }

    public ActionResult SignInWithTwitter()
    {
        //check for GetRedirectUrl and sets cookie
        Response.SetCookie(new HttpCookie("RedirectUrl",
            FormsAuthentication.GetRedirectUrl(string.Empty, false)));

        //build callback URL
        var callback_url_builder = new UriBuilder()
        {
            Host = Request.ServerVariables["SERVER_NAME"],
            Port = int.Parse(Request.ServerVariables["SERVER_PORT"]),
            Path = Url.Action("SignInWithTwitterCallback"),
        };

        //Helper funciton to invoke Twitter’s oauth/request_token REST endpoint
        var url = _twitter.GetRequestToken(callback_url_builder.ToString());

        //redirect to the URL returned from _twitter.GetRequestToken
        return Redirect(url);
    }

This code has several dependencies that are hard or impossible to test: FormsAuthentication, Request, Response and Url. Testing this code is a real pain in the ass. When I originally wrote this code, I bit the bullet and wrote said the PITA test code. But I couldn’t help thinking there must be a better way.

Clearly, in order to be able to test this code, I need to introduce points of abstraction that can be filled with mock implementations during unit test runs. I already have one such abstraction point – the _twitter field of AccountController is an ITwitterService instance that gets injected on construction. I have a “real” implementation that gets injected in production and a mock implementation that I manually inject in my tests.

In order to test the code above, I’ll need to wrap the calls into the untestable objects in some sort of injectable dependency that can be mocked out for tests.

C# being an OO language, typically we think of Dependency Injection in terms interfaces and classes. However, wrapping the untestables in interfaces and then implementing those interfaces is a lot of additional code. Instead of one injected dependency, the code above would need five injected dependencies. Furthermore, since objects are both the unit of dependency injection as well as the typical way the URL namespace is segmented, I also have to consider the dependencies of any other action methods on AccountController. That gets ugly fast.

Instead of thinking in terms of objects and interfaces, I wondered what DI might look like if we thought about dependencies in terms of delegates and anonymous lambdas? You know, functional programming?  It might look something like this:

Func<string> @GetRedirectUrl;
Action<HttpCookie> @SetCookie;
Func<NameValueCollection> @ServerVariables;
Func<string, string> @ActionUrl;

public ActionResult SignInWithTwitter()
{
    //check for GetRedirectUrl and sets cookie
    @SetCookie(new HttpCookie("RedirectUrl", @GetRedirectUrl()));

    //build callback URL
    var callback_url_builder = new UriBuilder
    {
        Host = @ServerVariables()["SERVER_NAME"],
        Port = int.Parse(@ServerVariables()["SERVER_PORT"]),
        Path = @ActionUrl("SignInWithTwitterCallback"),
    };

    //Call twitter.GetRequestToken
    var url = _twitter.GetRequestToken(callback_url_builder.ToString());

    //redirect to the URL returned from Twitter.GetRequestToken
    return Redirect(url);
}

(Note, I’m using the @ symbol as a prefix for injected delegates, in order to make it easier to pick them out of the code. Looks kinda odd, but it is valid C#.)

This is better in that it’s actually testable without requiring a metric crapload of test code to mock the ASP.NET intrinsics. However, this approach don’t have enough information to inject dependencies based on type alone. For example, the @GetRedirectUrl is a Func<string> (i.e. a function that takes no parameters and returns a string). However, FormsAuth FormsCookieName and DefaultUrl properties would also be represented as Func<string> delegates as well.

Most DI containers have support resolving dependencies by name and type, but that makes declaring dependencies much tougher and more fragile in my opinion. If you’re going to limit yourself to static typing write compiled code, you might as well let the compiler do as much heavy lifting as possible, right?

Also, wrapping each untestable method call in a delegate has made the explosion of dependencies problem even worse. SignInWithTwitter declares four new dependencies, the callback action (not shown) adds seven new delegate dependencies and the sign out action adds one, making a total of thirteen dependencies! (including the original ITwitterService). However, none of these twelve delegate dependencies are shared across action methods. So they aren’t really controller dependencies so much as action dependencies. So what if I went ahead and declared them as action dependencies directly?

public Func<ActionResult> SignInWithTwitter(
    Func<string> @GetRedirectUrl,
    Action<HttpCookie> @SetCookie,
    Func<NameValueCollection> @ServerVariables,
    Func<string, string> @ActionUrl)
{
    return () =>
    {
        //check for GetRedirectUrl and sets cookie
        SetCookie(new HttpCookie("RedirectUrl", GetRedirectUrl()));

        //build callback URL
        var callback_url_builder = new UriBuilder
        {
            Host = ServerVariables()["SERVER_NAME"],
            Port = int.Parse(ServerVariables()["SERVER_PORT"]),
            Path = ActionUrl("LogOnCallback"),
        };

        //Call twitter.GetRequestToken
        var url = _twitter.GetRequestToken(
            callback_url_builder.ToString());

        //redirect to the URL returned from Twitter.GetRequestToken
        return Redirect(url);
    };
}

SignInWithTwitter is now a function that takes four delegates and returns a delegate – we’re really down the functional programming rabbit hole now!

The benefit of this approach is that I can make tradeoffs as I see fit between controller and action dependencies. ITwitterService is still injected via the AccountController constructor since it is used by two of the three Account actions. Dependencies only used by a single action can be scoped to that specific action so that only tests for a given action method have to mock them out. And testing this is a breeze compared to having to mock out intrinsic ASP.NET objects.

[Fact]
public void returns_redirect_result_with_getrequesttoken_url()
{
    //inject controller dependencies
    var twitter = new Mock<Models.ITwitterService>(MockBehavior.Strict);
    twitter.Setup(t => t.GetRequestToken(It.IsAny<string>()))
        .Returns("http://fake.twittertest.local");
    var controller = new AccountController(twitter.Object);

    //inject action dependencies
    Func<string> @getRedirectUrl = () => "/fake/redirect/url";
    Action<HttpCookie> @setCookie = c => { };
    Func<NameValueCollection> @serverVariables =
        () => new NameValueCollection()
        {
            {"SERVER_NAME", "testapp.local"},
            {"SERVER_PORT", "8888"}
        };
    Func<string, string> @actionUrl = url => "/fake/url/action/result";
    var action = controller.SignInWithTwitter(@getRedirectUrl,
        @setCookie, @serverVariables, @actionUrl);

    //Invoke action
    var result = action();

    //Validate
    var redirectResult = Assert.IsType<RedirectResult>(result);
    Assert.Equal("http://fake.twittertest.local", redirectResult.Url);
}

I could make this code even smaller by moving the action dependencies out to be test fixture class fields. Assuming you write multiple tests for each action method, this allows you to reuse the mock action delegates across multiple methods. If I want to do negative testing, I can easily define test-specific delegates that throw exceptions or return unexpected values.

Of course, the down side to this approach is that MVC has no idea what to do with an action method that returns Func<ActionResult>. I could envision support for this pattern in MVC someday, though we’d need a robust solution to the type+name dependency issue I described above. For now, I will simply wrap the delegate injection version (aka the testable version) of the action in a non-testable but MVC compatible version that injects the right delegate dependencies.

public ActionResult SignInWithTwitter()
{
    return SignInWithTwitter(
        () => FormsAuthentication.GetRedirectUrl(string.Empty, false),
        Response.SetCookie,
        () => Request.ServerVariables,
        Url.Action)();
}

Since I’m using the untestable intrinsics, I can’t write any tests for this method. However, it’s nearly declarative because the anonymous delegates I’m injecting are closing over the untestable intrinsics. Personally, I’m willing to make the tradeoff of having an declarative yet untestable wrapper action method in order to get the delegate injected easy-to-test version of SignInWithTwitter that has the real implementation.

I Hate Global.asax

One of the things I’ve always loved about ASP.NET is how easily extensible it is. Back in 2000, I had a customer that wanted to “skin” their website using XML and XSLT – an approach Martin Fowler later called Transform View. We were working with classic ASP at the time, so the solution we ended up with was kind of ugly. But I was able to implement this approach in ASP.NET in a few hundred lines of code, which I wrote up in an MSDN article published back in 2003. In the conclusion of that article, I wrote the following:

Using ASP.NET is kind of like having your mind read. If you ever look at a site and think “I need something different,” you’ll most likely find that the ASP.NET architects have considered that need and provided a mechanism for you to hook in your custom functionality. In this case, I’ve bypassed the built-in Web Forms and Web Services support to build an entire engine that services Web requests in a unique way.

Nearly ten years later, I finally ran into a situation where ASP.NET failed to read my mind and doesn’t provide a mechanism to hook in custom functionality: Global.asax.

I always thought of global.asax as an obsolete construct primarily intended to ease migration from classic ASP. After all, ASP.NET has first class support for customizing request handling at various points throughout the execution pipeline via IHttpModule. Handling those events in global.asax always felt vaguely hacky to me.

However, what I didn’t realize is that there are some events that can only be handled via global.asax (or its code behind). In particular, Application_Start/End and Session_Start/End can only be handled in global.asax. Worse, these aren’t true events. For reasons I’m sure made sense at the time but that I don’t understand, the HttpApplicationFactory discovers these methods via reflection rather than by an interface or other more typical mechanism. You can check it out for yourself with Reflector or the Reference Source – look for the method with the wonderful name ReflectOnMethodInfoIfItLooksLikeEventHandler. No, I’m not making that up.

The reason I suddenly care about global.asax is because Application_Start is where ASP.NET MVC apps configure their route table. But if you want to access the Application_Start method in a dynamic language like IronPython, you’re pretty much out of luck. The only way to receive the Application_Start pseudo-event is via a custom HttpApplication class. But you can’t implement your custom HttpApplication in a dynamically typed language like IronPython since it finds the Application_Start method via Reflection. Ugh.

If someone can explain to me why ASP.NET uses reflection to fire the Application_Start event, I’d love to understand why it works this way. Even better – I’d love to see this fixed in some future version of ASP.NET. You come the only way to configure a custom HttpApplication class is to specify it via global.asax? Wouldn’t it make sense to specify it in web.config instead?

In order to support Application_Start for dynamic languages you basically have two choices:

  1. Build a custom HttpApplication class in C# and reference it in global.asax. This is kind of the approach used by Jimmy’s ironrubymvc project. He’s got a RubyMvcApplication which he inherits his GlobalApplication from. Given that GlobalApplication is empty, I think he could remove his global.asax.cs file and just reference RubyMvcApplication from global.asax directly.
  2. Build custom Application_Start/End-like events out of IHttpModule Init and Dispose. You can have multiple IHttpModule instances in a given web app, so you’d need to make sure you ran fired Start and End only once. This is the approach taken by the ASP.NET Dynamic Language Support. 1

So here’s the question Iron Language Fans: Which of these approaches is better? I lean towards Option #1, since it traps exactly the correct event though it does require a global.asax file to be hanging around (kind of like how the ASP.NET MVC template has a blank default.aspx file “to ensure that ASP.NET MVC is activated by IIS when a user makes a “/” request”). But I’m curious what the Iron Language Community at large thinks. Feel free to leave me a comment or drop me an email with your thoughts.


  1. FYI, I’m working on getting the code for ASP.NET Dynamic Language Support released. In the meantime, you can verify what I’m saying via Reflector.

Webdev Script and KillWebDevServer

I was updating my webdev powershell script today. I wanted to add support for a -browser switch that would automatically launch a browser window the way chiron from the Silverlight Dynamic Languages SDK. does. I also set the script to serve up the current directory by default. I posted the new version up on my SkyDrive.

While I was working on the script, I thought about how one might shutdown the WebDev server from the command line. That turned out to be much harder. Basically, you have to look thru all the top level windows for one that has “ASP.NET Development Server” in the window text, then you send that window two messages – WM_QUERYENDSESSION and WM_QUIT. Not sure why the WebDev server uses WM_QUERYENDSESSION to shut down it’s tray icon, but if you look at WebDev.WebServer.exe in Reflector, you’ll see the tray icon form overrides WinProc in order to look for message 0×11, i.e. WM_QUERYENDSESSION.

I threw together a quick little C# console app to shutdown the WebDev server and stuck it up on my SkyDrive as well. Source code is up there too. I had to use a bunch of P/Invokes to make it work, or I would have written it in Powershell or IronPython.

Enjoy.

Afternoon Coffee 174

You know, this gets pretty long when I go a week between morning coffee posts.

Dynamic Language Stuff

Other Stuff

  • Don Syme blogs about an update to the F# CTP, a mere week after the original release. One week? That’s more often than even IPy releases. I can’t wait to see what they ship in next week’s release! 😄 Seriously, I hope they can keep the release sprints short, but every week would be a bit crazy!
  • Speaking of F#, Matt Podwysocki updates FsTest for the F# CTP and posts about Extension Everything in F#. Unlike C#, which only supports extension methods, F# also supports extensions properties, static methods and events, though like Matt I can’t think of a good use for extension events.
  • Still speaking about F#, Andrew Kennedy has a three part series on the new units of measure feature of F#. If you were going to use F# to build the physics engine of a game, I would suspect UoM would be extremely useful. (via Don Syme)
  • Oh look, Chris Smith built an F# version of artillery game that uses Units of Measure for the physics code. I’ll bet UoM was extremely useful. 😄
  • Talking about Live Mesh at TechEd Australia – where much to my surprise frankly they were demoing Live Mesh Apps – I pointed out to Scott Hanselman that Mesh is running an embedded CoreCLR (aka the same CLR from Silverlight 2). Scott went poking around and posted what he discovered. Looking forward to finding out what he digs up on using CoreCLR outside the browser.
  • Speaking of Scott, I need to set up a family video conference solution like Scott’s before my next trip.
  • Congrats to Glenn Block and the MEF team for their initial CodePlex source drop! I’ve been hearing about this possibility since Glenn joined the team, so I’m really excited to see it happen. I need to take a look at it in detail (in my copious spare time) because I want to find out how to make it work with IPy.
  • Bart de Smet has a whole series (starting here) on Dynamic Expression Trees. However, given that he specifically writes “This blog series is not about DLR itself” makes it seem pretty conceptual to me. Why not talk about DLR expression trees instead Bart?
  • I’m sure you noticed ASP.NET MVC preview 5 dropped last week. I really liked Brad Wilson’s discussion of the new view engine design.
  • Tomas Restrepo has started publishing his source code on GitHub. Personally, I haven’t published any source code lately but I am using Git for all of my non IPy core work (which is stored in TFS). Like Tomas, I’m still getting the hang of Git but I’m really digging it’s speed, it’s branching and the fact that there’s zero infrastructure requirements. SVN provides the lightweight svnserve, but Git is even lighter weight than that.
  • I liked Steve Yegge’s post on typing. I am a touch typer, but I doubt I type 70 words a minutes. I do know where the number keys are without looking though, so I guess that’s pretty good. I remember seeing Chris Anderson demo Avalon WPF long before it was public and being impressed at how fast he could type.

Five Minutes Past Noon Coffee 170

  • Ben Hall announces IronEditor, a simple dev tool for IronPython and IronRuby. Pretty nice, though fairly simplistic (as Ben readily admits). For example, it doesn’t have an interactive mode, only the ability to execute scripts and direct the output to IronEditor’s output window. However, it is a good start and I’m sure it’ll just get better. One thing he’s apparently considering is a Silverlight version. (via Michael Foord)
  • Speaking of “Iron” tools, Sapphire Steel have had an IronRuby version (in alpha) of their Ruby in Steel product for several months now. I wonder if John’s had a chance to play with it.
  • Speaking of John, the ASP.NET MVC / IronRuby prototype he talked about @ TechEd is now available on ASP.NET MVC Preview 4 via Phil Haack.
  • Ted Neward has an article exploring the IronPython VS Integration sample that ships in the VS SDK. As I mentioned the other day, we’re starting working on a production quality implementation of VS Integration for IPy.
  • Ophir Kra-Oz (aka Evil Fish) blogs Python for Executives. I like his “Risk, Recruiting, Performance and Maturity” model – four boxes, perfect for keeping an executive’s attention! 😄 Plus Ophir has some nice things to say about IronPython. (via Michael Foord)
  • Ronnie Maor blogs an extension method for PythonEngine to make Eval simpler. I especially like how he uses string format syntax so you can dynamically generate the code to eval. I wonder what this would look like in IPy 2.0 with DLR Hosting API. (via IronPython URLs)
  • Speaking of DLR Hosting, Seshadri has another great DLR hosting post, this time hosting IPy inside of VS08 so you can script VS08 events (document saved, window created, etc) with Python.
  • Justin Etheredge has a bunch of IronRuby posts – Getting IronRuby Up and Running, Running Applications in IronRuby, Learning Ruby via IronRuby and C# Part 1. (via Sam Gentile)
  • Don Syme links to several F# related posts by Ray Vernagus, though he’s apparently also experimenting with IronRuby. I’m really interested in his Purely Functional Data Structures port to F#.
  • Speaking of F#, Brian has a teaser screenshot of F# upcoming CTP. However, he chooses the New Item dialog to tease, which looks pretty much like the current new item dialog (the new one does have fewer F# templates). However, if you look in the Solution Explorer, you’ll notice a real “References” node. No more #I/#R! Yeah!
  • The interactive graphic in Kevin Kelly’s One Machine article is fascinating. It really highlights that the vast vast vast majority of power, storage, CPU cycles and RAM come from personal computers on the edge. Even in bandwidth, where PC’s still have the highest share but it looks to be around 1/3rd, the aggregate of all edge devices (PCs, mobile phones, PDAs, etc.) still dominates the data centers.