Created
December 14, 2012 03:18
-
-
Save tathamoddie/4282432 to your computer and use it in GitHub Desktop.
Some common unit tests that I like to apply to ASP.NET MVC projects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Reflection; | |
using System.Security.Permissions; | |
using System.Web.Mvc; | |
using Example.Web; | |
using NUnit.Framework; | |
namespace Example.UnitTests.Web | |
{ | |
[TestFixture] | |
public class ActionTests | |
{ | |
[Test] | |
[TestCaseSource(typeof(AllMvcActions), "GetActions")] | |
public void AllActionsShouldBeExplicitlyGetOrPost(MethodInfo action) | |
{ | |
if (action.GetCustomAttributes(typeof (ChildActionOnlyAttribute), false).Any() || | |
action.GetCustomAttributes(typeof (HttpDeleteAttribute), false).Any() || | |
action.GetCustomAttributes(typeof (HttpGetAttribute), false).Any() || | |
action.GetCustomAttributes(typeof (HttpPostAttribute), false).Any() || | |
action.GetCustomAttributes(typeof (HttpPutAttribute), false).Any()) | |
return; | |
if (action.DeclaringType == null) | |
throw new InvalidOperationException("An assumption about reflection was just proven wrong: action.DeclaringType was null. Test failed (method may or may not actually be correct)."); | |
Assert.Fail("{0}.{1} is missing one of [ChildActionOnly], [HttpDelete], [HttpGet], [HttpPut] or [HttpPost]", action.DeclaringType.Name, action.Name); | |
} | |
[Test] | |
[TestCaseSource(typeof(AllMvcActions), "GetActions")] | |
public void AllMutatingActionsShouldHaveAntiForgeryValidation(MethodInfo action) | |
{ | |
var isMutatingAction = | |
action.GetCustomAttributes(typeof(HttpDeleteAttribute), false).Any() || | |
action.GetCustomAttributes(typeof(HttpPutAttribute), false).Any() || | |
action.GetCustomAttributes(typeof(HttpPostAttribute), false).Any(); | |
if (!isMutatingAction) | |
return; | |
if (action.GetCustomAttributes(typeof(ValidateAntiForgeryTokenAttribute), false).Any()) | |
return; | |
if (action.DeclaringType == null) | |
throw new InvalidOperationException("An assumption about reflection was just proven wrong: action.DeclaringType was null. Test failed (method may or may not actually be correct)."); | |
Assert.Fail("{0}.{1} is marked with [HttpDelete], [HttpPut] or [HttpPost] but missing [ValidateAntiForgeryToken]", action.DeclaringType.Name, action.Name); | |
} | |
[Test] | |
[TestCaseSource(typeof(AllMvcActions), "GetActions")] | |
public void AllMutatingActionsShouldHaveAuthorizeOrAllowAnonymous(MethodInfo action) | |
{ | |
var isMutatingAction = | |
action.GetCustomAttributes(typeof(HttpDeleteAttribute), false).Any() || | |
action.GetCustomAttributes(typeof(HttpPutAttribute), false).Any() || | |
action.GetCustomAttributes(typeof(HttpPostAttribute), false).Any(); | |
if (!isMutatingAction) | |
return; | |
if (action.GetCustomAttributes(typeof(AuthorizeAttribute), false).Any() || | |
action.GetCustomAttributes(typeof(AllowAnonymousAttribute), false).Any()) | |
return; | |
if (action.DeclaringType == null) | |
throw new InvalidOperationException("An assumption about reflection was just proven wrong: action.DeclaringType was null. Test failed (method may or may not actually be correct)."); | |
Assert.Fail("{0}.{1} is marked with [HttpDelete], [HttpPut] or [HttpPost] but missing either [Authorize] or [AllowAnonymous]", action.DeclaringType.Name, action.Name); | |
} | |
[Test] | |
[TestCaseSource(typeof(AllMvcActions), "GetActions")] | |
public void AllAuthorizeActionsShouldHavePrincipalPermissionAttribute(MethodInfo action) | |
{ | |
if (!action.GetCustomAttributes(typeof(AuthorizeAttribute), false).Any()) | |
return; | |
if (action.GetCustomAttributes(typeof(PrincipalPermissionAttribute), false).Any()) | |
return; | |
if (action.DeclaringType == null) | |
throw new InvalidOperationException("An assumption about reflection was just proven wrong: action.DeclaringType was null. Test failed (method may or may not actually be correct)."); | |
Assert.Fail("{0}.{1} is marked with [Authorize] but missing [PrincipalPermission(SecurityAction.Demand, Role=UserRoles.Something)]. You should be explicit about which roles are allowed to call something.", action.DeclaringType.Name, action.Name); | |
} | |
public class AllMvcActions | |
{ | |
public IEnumerable<MethodInfo> GetActions() | |
{ | |
var controllers = typeof(MvcApplication) | |
.Assembly | |
.GetTypes() | |
.Where(t => typeof(Controller).IsAssignableFrom(t)); | |
var actions = controllers | |
.SelectMany(c => c.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)) | |
.Where(m => !m.IsSpecialName); | |
return actions; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment