Usually, when writing code, you adhere to some conventions on how your stuff should work. At least I hope you do – otherwise your code is probably a mess!
Sometimes, these conventions can be enforced by using some patterns to allow for compile-time checking – one example, that I can think of right now, is using the visitor pattern to implement multiple dispatch, which is explored a little bit in another post.
But what about conventions, that can only be checked at runtime? Well, how do we usually check stuff that can only be checked at runtime? – by writing tests, of course!
One project I am currently involved in, is written in ASP.NET MVC. All form posts are done using the automatic binding features of the framework, and I am following the convention that the names of my view models should end in “Form” – so as to enabling me to easily distinguish my form posting DTOs from my other view models. What is more natural, then, than performing the following test:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | [Test] public void ActionParametersAreEitherPrimitiveTypesOrTruePocos() { 	var assembly = Assembly.GetAssembly(typeof (HomeController)); 	var types = assembly.GetTypes().ToList(); 	types 		.FindAll(ThatIsConcreteController) 		.SelectMany(t => t.GetMethods().ToList().FindAll(ControllerActions)) 		.ToList() 		.ForEach(CheckMethodInfo); } bool ControllerActions(MethodInfo info) { 	return info.IsPublic && typeof(ActionResult).IsAssignableFrom(info.ReturnType); } void CheckMethodInfo(MethodInfo info) { 	var parameters = info.GetParameters().ToList(); 	parameters.ForEach(p => CheckParameterType(info, p)); } void CheckParameterType(MethodInfo methodInfo, ParameterInfo parameterInfo) { 	Assert.IsTrue(IsPrimitiveType(parameterInfo) || IsFormType(parameterInfo), 	              string.Format( 	              	"Action {0} of {1} has parameter of type {2} which is invalid. Use only true pocos from the view models assembly.", 	              	methodInfo.Name, 	              	methodInfo.DeclaringType.Name, 	              	parameterInfo.ParameterType.Name)); } bool IsFormType(ParameterInfo info) { 	var type = info.ParameterType; 	return 		type.Assembly == Assembly.GetAssembly(typeof (LogInForm)) 		&& type.Name.EndsWith("Form"); } bool IsPrimitiveType(ParameterInfo info) { 	// add mores types here if they should be allowed as well 	return 		new List<Type> 			{ 				typeof (int), 				typeof (string), 				typeof(int?), 				typeof(Guid) 			}.Contains(info.ParameterType); } bool ThatIsConcreteController(Type type) { 	return typeof(Controller).IsAssignableFrom(type) && !type.IsAbstract; } | 
That is, I am running through all controller types, getting all actions, and checking the the parameter types are either in the array of accepted types ( IsPrimitiveType) or a “true poco” (which in this application is a simple view model whose name ends with “Form” and comes from the right assembly).
This way, I will always know which types are used to deserialize forms. Great! But what about that pesky MissingMethodException whenever I forget to provide a public default contructor in my form models? Easy as cake! That part is checked by the following test:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | [Test] public void AllFormModelsHavePublicDefaultConstructor() { 	var assembly = Assembly.GetAssembly(typeof (LogInForm)); 	var types = assembly.GetTypes().ToList(); 	types 		.FindAll(ThatCouldBePoco) 		.FindAll(ThatSatisfiesPocoNamingConvention) 		.ForEach(AssertHasPublicDefaultConstructor); } bool ThatCouldBePoco(Type type) { 	return type.IsClass 	       && !type.IsAbstract; } bool ThatSatisfiesPocoNamingConvention(Type type) { 	var name = type.Name; 	return name.EndsWith("Form"); } void AssertHasPublicDefaultConstructor(Type type) { 	var constructors = type.GetConstructors().ToList(); 	Assert.IsTrue(constructors.Exists(IsPublicDefaultConstructor), 	              string.Format("Poco type {0} does not provide a public default constructor.", 	                            type.Name)); } bool IsPublicDefaultConstructor(ConstructorInfo info) { 	var parameters = info.GetParameters(); 	return parameters.Length == 0; } | 
These two tests combined, will assert that nothing will go wrong when submitting forms in my ASP.NET MVC project. That’s just nifty! And I really like the notion that I am helping future me.