Enforcing a Base Controller

Tuesday, June 29, 2010

In the previous post we talked about using a base controller class in ASP.NET MVC. The truly paranoid will worry about new developers on the team who don't know the rules and don't use the base class. One automated solution to this problem is to write a unit test to enforce the rule.

[TestMethod]
public void AllControllersDeriveFromFootballController()
{
    var badControllers =
        GetConcreteTypesAssignableTo<IController>()
       .Where(TypeIsNotDerivedFrom<FootballController>);

    if(badControllers.Any())
    {
        var controllerNames = AggregateTypeNames(badControllers);
        

        Assert.Fail("Controllers are out of line: {0}", 
                     controllerNames);
    }            
}

The above code uses a few helper methods:

IEnumerable<Type> GetConcreteTypesAssignableTo<T>()
{
    return
        Assembly
            .GetExecutingAssembly()
            .GetReferencedAssemblies()
            .Select(name => Assembly.Load(name.FullName))
            .SelectMany(assembly => assembly.GetTypes())
            .Where(type => typeof (T).IsAssignableFrom(type))
            .Where(type => !type.IsAbstract);
}

bool TypeIsNotDerivedFrom<TBase>(Type type)
{
    return !(typeof (TBase).IsAssignableFrom(type));
}

string AggregateTypeNames(IEnumerable<Type> types)
{
    return
        types
            .Select(type => type.Name)
            .Aggregate(new StringBuilder(),
                       (sb, name) => sb.Append(name + " "))
            .ToString();
}

Of course the test isn't so simple if controllers might use different base classes (think asynchronous controllers), and I'm sure some people question the value of a test like this in any case. Right?


Comments
gravatar Wyatt Barnett Wednesday, June 30, 2010
But what if the junior devs skip the tests (as they are wont to do)? Then you can be even more insidious and enforce it in the controller factory too, so their stuff will blow up in the debugger.

Yeah, I've had lots of bad junior devs . . ..
gravatar scott Wednesday, June 30, 2010
@Wyatt - how have you been? Yes, controller factory would be an easy place to check.
gravatar Nick Wednesday, June 30, 2010
Another thing that can help is to modify the T4 template used to create Controllers so that the base class inheritance is automatically wired up from the start. I've had good results from this in the projects I work on.
gravatar Caio Kinzel Filho Wednesday, September 15, 2010
@Wyatt: if a dev forget to run tests, that is why we have CI right?! :)

Also, what you guys think about IoC interception features to register those action filters?
gravatar Caio Kinzel Filho Wednesday, September 15, 2010
@Wyatt: if a dev forget to run tests, that is why we have CI right?! :)

Also, what you guys think about IoC interception features to register those action filters?
Comments are now closed.
by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!