【问题标题】:ASP.Net MVC 4 Custom ValidationAttribute Dependency InjectionASP.Net MVC 4 自定义 ValidationAttribute 依赖注入
【发布时间】:2013-11-26 14:11:13
【问题描述】:

在我目前正在处理的 ASP.Net MVC 4 应用程序中,有许多具有仓库属性的模型。我希望所有这些模型都经过验证,以确保输入的仓库是有效的仓库。似乎最简单的方法是使用自定义 ValidationAttribute 类。然后验证代码将被集中,我可以将属性添加到每个模型的属性中。

我需要调用服务以确保仓库是有效的仓库。我有一个代表此服务的接口,并且我正在使用 Ninject 在使用此服务的应用程序中进行依赖注入。这样我就可以使用模拟并轻松地对应用程序进行单元测试。

我希望我的自定义 ValidationAttribute 类在使用此服务时使用依赖注入。这是我创建的类:

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>();
    }
}

依赖注入可以正常工作,但是不容易测试。无法在单元测试中将模拟 IInventService 注入到类中。通常为了解决这个问题,我会让类构造函数接受一个 IInventService 参数,这样我就可以在我的单元测试中传入一个模拟对象。但是我不认为我可以让这个类构造函数将 IInventService 类作为参数,因为我相信当我在我的类中添加这个属性时我必须传入那个参数。

有没有办法让这段代码更容易测试?如果没有,那么有没有更好的方法来解决这个问题?

【问题讨论】:

  • 一个很好的问题。很高兴阅读!

标签: c# asp.net asp.net-mvc unit-testing dependency-injection


【解决方案1】:

您需要在 ASP.NET MVC 中使用DependencyResolver 类。如果您正确连接您的容器DependencyResolver.Current 将使用您的容器来解决依赖关系。

public class MustBeValidWarehouse : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        if (value is string)
        {
            string warehouse = value.ToString();
            IInventService inventserv = DependencyResolver.Current.GetService<IInventService>();
            return (inventserv.GetWarehouses().Where(m => m.WarehouseId == warehouse).Count() != 0);
        }
        return false;
    }
}

在您的课堂测试中,您可以像这样为DepedencyResolver.Current 提供模拟:

DependencyResolver.SetResolver(resolverMock);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-02
    相关资源
    最近更新 更多