In a ASP.Net MVC 4 application that I am currently working on there are a number of models that have a warehouse property. I want all of these models to have validation that makes sure that the warehouse entered is a valid warehouse. It seemed like the easiest way to do this was to use a custom ValidationAttribute class. Then the validation code would be centralized, and I could just add the attribute to the property in each of the models.
I need to call a service to make sure that the warehouse is a valid warehouse. I have a interface that represents this service and I am using Ninject to do dependency injection in my applications where this service is used. That way I can use mocking and easily do unit testing on the application.
I want my custom ValidationAttribute class to use dependency injection when using this service. Here is the class that I have created:
public class MustBeValidWarehouse : ValidationAttribute { public override bool IsValid(object value) { if (value is string) { string warehouse = value.ToString(); NinjectDependencyResolver depres = new NinjectDependencyResolver(); Type inventServiceType = typeof(IInventService); IInventService inventserv = depres.GetService(inventServiceType) as IInventService; return (inventserv.GetWarehouses().Where(m => m.WarehouseId == warehouse).Count() != 0); } else { return false; } } } public class NinjectDependencyResolver : IDependencyResolver { private IKernel kernel; public NinjectDependencyResolver() { kernel = new StandardKernel(); AddBindings(); } public object GetService(Type serviceType) { return kernel.TryGet(serviceType); } public IEnumerable<object> GetServices(Type serviceType) { return kernel.GetAll(serviceType); } private void AddBindings() { kernel.Bind<IInventService>().To<InventService>(); } } The dependency injection works correctly, however it is not easy to test. There is no way to inject a mock IInventService into the class in a unit test. Normally in order to resolve this I would have the class constructor take a IInventService parameter so that I could pass in a mock object in my unit test. However I don't think that I can have this class constructor take a IInventService class as a parameter because then I believe that I would have to pass in that parameter when I added this attribute in my class.
Is there a way to make this code more testable? If not then is there a better way to approach this?