依赖注入解析和单元测试
-
03-07-2019 - |
题
我正在尝试学习依赖注入,并在对应用程序进行单元测试时遇到了问题。
我正在编写一个控制台应用程序,容器是在 Main() 中创建和初始化的,它可以作为 get-property
在 Program.Container
, ,所以我可以在我的应用程序中的任何地方调用 Program.Container.Resolve<..>()
.
我有一个像这样的 ServiceValidator 类:
public class ServiceValidator
{
private readonly IConfiguration _configuration;
private readonly IService _service;
public ServiceValidator(IConfiguration configuration, IService service)
{
_configuration = configuration;
_service = service;
}
在我使用的另一堂课中
ServiceValidator serviceValidator = Program.Container.Resolve<ServiceValidator>();
serviceValidator.VerifyVersion();
这是呼叫 Program.Container.Resolve
这导致我在单元测试中出现问题,因为它尚未设置。
在容器上调用解析是一种不好的做法吗?我可以在中创建 ServiceValidator 实例 Main()
并传递对象,但这似乎很愚蠢,因为它会导致对象的大量参数被传递到下一个方法。
所以我想在类中调用 Resolve 是可以接受的,但是必须为单元测试配置容器。我应该怎么做,我应该将容器移动到 Program 类之外的其他地方吗?你会推荐什么?
如果重要的话,我正在使用 Unity 和 C#
谢谢 :-)
解决方案
在容器上调用解析是一种不好的做法吗?我可以在 Main() 中创建 ServiceValidator 实例并传递对象,但这看起来很愚蠢,因为它会导致对象的大量参数被传递到下一个方法。
当您一直使用依赖注入时,您将不需要向对象传递大量参数。每个对象的构造函数应该仅将其本身直接使用的那些依赖项作为参数 - 它不会知道其直接依赖项的传递依赖项。
因此,如果您有一个需要 ServiceValidator 的类 X,那么类 X 将具有一个 ServiceValidator 类型的构造函数参数。那么如果某个类Y使用类X,那么类Y将有一个类型为X的构造函数参数。请注意,Y 什么都不知道 关于 ServiceValidator,因此您不需要将 ServiceValidator 从一个类传递到另一个类 - 唯一使用它的地方是构造 X 时,并且这通常由 DI 框架完成或仅在手写的一个地方完成工厂。
更多信息的一些链接:
- http://martinfowler.com/articles/injection.html
- http://www.youtube.com/watch?v=RlfLCWKxHJ0 - 关于传递对象的问题从 19:20“关于 DI 的神话”开始得到解答
其他提示
我通常允许调用来解决像main这样的容器中的依赖关系,尽管我仍然试图将它们保持在最低限度。然后我做的是在测试类的初始化方法中配置容器。我已经使用假实现初始化了任何需要调用容器的测试类。
不会调用任何需要容器的任何东西的测试类然后能够忽略它并且不使用假货。我经常在那些情况下使用模拟。
我还使用 Microsoft服务定位器,以便依赖我正在使用的是.NET Framework中的某些内容,而不是特定容器上的内容。这使我可以在路上使用任何我想要的东西,甚至是自酿的容器。
您可以使用静态类作为容器的初始化程序。像BootStrapper.cs之类的东西就好了。然后,您可以在代码和测试中引用类方法。
你在技术上做的是你班上的服务地点。
我记得有一段时间读过这篇文章:
http://martinfowler.com/articles/injection.html
对于我的课程,我从不尝试在其中使用Resolve。我需要时通过容器创建对象。对于单元测试,我要么使用一些模拟库和存根类。
问题在于您正在尝试测试 Main 方法。这种方法实际上不可能进行单元测试。
我认为最好不要对 Main 方法进行单元测试,因为:
- 现代单元测试的重点是设计
- 您应该最大限度地减少对单元测试中配置的依赖。可以通过冒烟测试或集成测试来测试配置。