如何模拟container.Resolve()

发布于 2024-08-12 09:58:36 字数 251 浏览 7 评论 0原文

当单元测试时,我有一个类似的东西,

public class HomeController
{
   public ActionResult Index()
   {
      var x = Container.Resolve<IOrganisationService>();
   }
}

当容器尝试解析时,我得到一个空引用异常
有人知道如何模拟 Container.Resolve() 吗?

i have a something like this

public class HomeController
{
   public ActionResult Index()
   {
      var x = Container.Resolve<IOrganisationService>();
   }
}

when unit testing i get a null reference exception when the container tries to resolve

anybody knows how do to mock Container.Resolve() ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

暮年慕年 2024-08-19 09:58:36

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

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

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

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 实例。这是一个更加灵活的解决方案。

You can't, because the Resolve method in question is a static method. This is one of the many reasons static types are considered evil when it comes to unit testing (and hence for general composability of code).

You seem to be applying an (anti)pattern known as Service Locator, and you are currently experiencing one of the many problems associated with it.

A better solution would be to use Constructor Injection like this:

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...
   }
}

You can now let your DI Container of choice resolve the HomeController instance from the outside. This is a much more flexible solution.

等风来 2024-08-19 09:58:36

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

public class HomeController
{
    private readonly IOrganisationService organisationService;

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

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

The question is, why are you resolving it in that fashion? If you instead have the dependency injected, then you can easily mock:

public class HomeController
{
    private readonly IOrganisationService organisationService;

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

   public ActionResult Index()
   {
      var x = this.organisationService;
   }
}
你げ笑在眉眼 2024-08-19 09:58:36

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

不过,我同意上面的帖子。您实际上不需要从代码中引用容器。这将您的应用程序与容器耦合在一起,这是您通过使用容器试图避免的事情。

Some containers (Windsor for example) have a container which inherits from an interface. If you use this then it is implicitly mockable. If you have created a static method that you can call resolve on, then as stated above it cannot be mocked isn't advisable. If your container doesn't inherit from an interface (or the service locator pattern you are using) relies on a static method then change the implementation so it's instance based and therefore mockable.

However, I agree with the posts above. You shouldn't really need to reference your container from within your code. This couples your application to a container which is of the things you are trying to avoid by using a container.

紫轩蝶泪 2024-08-19 09:58:36

我做到了,是这样的:

//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);

I did it, it's like this:

//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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文