C# 如何模拟容器。解决(<;类型>;()

C# 如何模拟容器。解决(<;类型>;(),c#,moq,ioc-container,C#,Moq,Ioc Container,我有一个类似这样的想法 public class HomeController { public ActionResult Index() { var x = Container.Resolve<IOrganisationService>(); } } 公共类HomeController { 公共行动结果索引() { var x=Container.Resolve(); } } 当单元测试时,当容器尝试解析时,我得到一个空引用异常 有人知道如何模拟C

我有一个类似这样的想法

public class HomeController
{
   public ActionResult Index()
   {
      var x = Container.Resolve<IOrganisationService>();
   }
}
公共类HomeController
{
公共行动结果索引()
{
var x=Container.Resolve();
}
}
当单元测试时,当容器尝试解析时,我得到一个空引用异常

有人知道如何模拟Container.Resolve()?

问题是,为什么要以这种方式解决它?相反,如果注入依赖项,则可以轻松模拟:

public class HomeController
{
    private readonly IOrganisationService organisationService;

    public HomeController(IOrganisationService organisationService)
    {
        this.organisationService = organisationService;
    }

   public ActionResult Index()
   {
      var x = this.organisationService;
   }
}

您不能,因为所讨论的Resolve方法是静态方法。这是在单元测试(以及代码的一般可组合性)中,静态类型被认为是邪恶的众多原因之一

您似乎正在应用一种称为服务定位器(ServiceLocator)的(反)模式,并且您当前正遇到与此相关的许多问题之一

更好的解决方案是使用构造函数注入,如下所示:

public class HomeController
{
   private readonly IOrganisationService organisationService;

   public HomeController(IOrganisationService organisationService)
   {
       if (organisationService == null)
       {
           throw new ArgumentNullException("organisationService");
       }

       this.organisationService = organisationService;
   }

   public ActionResult Index()
   {
      var x = this.organisationService;
      // return result...
   }
}
现在可以让您选择的DI容器从外部解析HomeController实例。这是一个更加灵活的解决方案。

一些容器(例如Windsor)具有从接口继承的容器。如果您使用这个,那么它是隐式可模仿的。如果您已经创建了一个可以调用resolve的静态方法,那么如上所述,不建议对其进行模拟。如果您的容器不是从依赖静态方法的接口(或您正在使用的服务定位器模式)继承的,那么请更改实现,使其基于实例,因此是可模拟的


然而,我同意上面的帖子。您不应该真的需要从代码中引用容器。这会将您的应用程序耦合到一个容器,而容器是您试图通过使用容器来避免的事情之一

我做到了,就像这样:

//code inside the setup method
 var c = new Moq.Mock<IWindsorContainer>();
 var l = new Moq.Mock<ILookupService>();
 l.Setup(o => o.GetItems(It.IsAny<String>())).Returns(new List<LookupItem>());
 c.Setup(o => o.Resolve<ILookupService>()).Returns(l.Object);
 LocatorConfigurator.SetContainer(c.Object);
//安装方法中的代码
var c=新的最小起订量Mock();
var l=新的最小起订量。模拟();
l、 Setup(o=>o.GetItems(It.IsAny()).Returns(newlist());
c、 设置(o=>o.Resolve())。返回(l.Object);
LocatorConfigurator.SetContainer(c.Object);

你用什么做容器?不,不是那样的,我只是想简化一下,实际上我需要它way@Omu当前位置你为什么需要它?我会尽量避免这种情况,并使用上面马克和肯特展示的内容。