I'm starting development on a new MVC application that will be largely written using TDD. I'd like to add some integration tests to ensure that the fully wired application (I'm using StructureMap for IOC, NHibernate for persistence) works as expected.
While I intend to write a few functional smoke tests with Selenium, for maintainability reasons, I'd rather do my most of integration testing by directly calling actions on my controllers using good old C#.
There is surprisingly little guidance on how one would accomplish this, so I took a stab on a plan of attack
- Pull all bootstrapping code out of Global.asax and into a separate class
- Attempt to leverage MvcContrib-TestHelper or similar to create ASP.NET dependencies (Context, Request, etc)
I've accomplished step 1, but really have no idea how to proceed to step 2. Any guidance would be appreciated.
public class Bootstrapper
{
public static void Bootstrap()
{
DependencyResolverInitializer.Initialize();
FilterConfig.RegisterFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
ModelBinders.Binders.DefaultBinder = new SharpModelBinder();
}
}
public class DependencyResolverInitializer
{
public static Container Initialize()
{
var container = new Container();
container.Configure(x => x.Scan(y =>
{
y.Assembly(typeof(Webmin.UI.FilterConfig).Assembly);
y.WithDefaultConventions();
y.LookForRegistries();
}));
DependencyResolver.SetResolver(new StructureMapDependencyResolver(container));
return container;
}
}
public class StructureMapDependencyResolver : IDependencyResolver
{
private readonly IContainer _container;
public StructureMapDependencyResolver(IContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
if (serviceType.IsAbstract || serviceType.IsInterface) {
return _container.TryGetInstance(serviceType);
}
return _container.GetInstance(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.GetAllInstances(serviceType).Cast<object>();
}
}
If you want to do automated end-to-end testing of an ASP.NET MVC application without going through the UI, one good way to do it is to programmatically send HTTP requests to the different URLs and assert the state of the system afterwards.
Your integration tests would basically look like this:
You can easily host an ASP.NET web app in an in-process web server using CassiniDev. Also, one convenient way to send HTTP requests programmatically is to use the Microsoft ASP.NET Web API Client Libraries.
Here's an example:
If you're looking for a more complete example of this technique in action, you can find it in a sample MVC 4 web application of mine, where I demonstrated it in the context of writing automated acceptance tests.