如何在测试中管理 IoC 容器?

发布于 2024-09-02 21:18:47 字数 173 浏览 8 评论 0原文

我对测试和 IoC 容器非常陌生,并且有两个项目:

  • MySite.Website (MVC)
  • MySite.WebsiteTest

目前我的网站中有一个 IoC 容器。我应该为我的测试重新创建另一个 IoC 容器吗?或者有没有办法在两者中使用 IoC?

I'm very new to testing and IoC containers and have two projects:

  • MySite.Website (MVC)
  • MySite.WebsiteTest

Currently I have an IoC container in my website. Should I recreate another IoC container for my test? Or is there a way to use the IoC in both?

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

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

发布评论

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

评论(2

长途伴 2024-09-09 21:18:53

测试是关于实际实施的。所以你通常不应该在单元测试中使用 IOC。如果您确实觉得需要它(一个组件依赖于另一个组件),请使用接口来隔离交互并使用模拟库(起订量很好)来模拟它并进行测试。

我唯一一次看到 IOC 容器对于测试来说是必需的是在集成测试中。

Testing is about real implementation. So you normally should not use IOC in your unit tests. In case you really feel needing it (one component depending on another one), using an interface to isolate the interaction and using a mocking lib (Moq is good) to mock it and do the testing.

The only chance I see IOC container is necessary for testing is in integration testing.

一袭白衣梦中忆 2024-09-09 21:18:51

当您拥有 IoC 容器时,希望您还会进行某种依赖注入 - 无论是通过构造函数还是 setter 注入。

单元测试的重点是单独测试组件,而 DI 对此有很大帮助。您想要做的是通过手动构造每个类并向其传递所需的依赖项来对每个类进行单元测试,而不是依赖容器来构造它。

这样做的目的很简单。您希望尽可能隔离 SUT(被测系统)。如果您的 SUT 依赖于另一个类和 IoC 来注入它,那么您实际上是在测试三个系统,而不是一个。

举个例子:

public class ApiController : ControllerBase {

  IRequestParser m_Parser;

  public ApiController(IRequestParser parser) {
    m_Parser = parser;
  }

  public ActionResult Posts(string request) {
    var postId = m_Parser.GetPostId(request);
  }
} 

ApiController 构造函数是一个依赖构造函数,将在运行时被 IoC 容器调用。然而,在测试过程中,您需要模拟 IRequestParser 接口并手动构建控制器。

[Test]
public void PostsShouldCallGetPostId() {
  //use nmock for mocking
  var requestParser = m_Mocks.NewMock<IRequestParser>();
  //Set up an expectation that Posts action calls GetPostId on IRequestParser
  Expect.Once.On(requestParser).Method("GetPostId").With("posts/12").Will(Return.Value(0));
  var controller = new ApiController(requestParser);
  controller.Posts("posts/12");
}

When you have an IoC container, hopefully you will also have some sort of dependency injection going on - whether through constructor or setter injection.

The point of a unit test is to test components in isolation and doing DI goes a long way in aiding that. What you want to do is unit test each class by manually constructing it and passing it the required dependencies, not rely on container to construct it.

The point of doing that is simple. You want to isolate the SUT(System Under Test) as much as possible. If your SUT relies on another class and IoC to inject it, you are really testing three systems, not one.

Take the following example:

public class ApiController : ControllerBase {

  IRequestParser m_Parser;

  public ApiController(IRequestParser parser) {
    m_Parser = parser;
  }

  public ActionResult Posts(string request) {
    var postId = m_Parser.GetPostId(request);
  }
} 

The ApiController constructor is a dependency constructor and will get invoked by IoC container at runtime. During test, however, you want to mock IRequestParser interface and construct the controller manually.

[Test]
public void PostsShouldCallGetPostId() {
  //use nmock for mocking
  var requestParser = m_Mocks.NewMock<IRequestParser>();
  //Set up an expectation that Posts action calls GetPostId on IRequestParser
  Expect.Once.On(requestParser).Method("GetPostId").With("posts/12").Will(Return.Value(0));
  var controller = new ApiController(requestParser);
  controller.Posts("posts/12");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文