【问题标题】:How can I unit test that my DI is configured correctly如何对我的 DI 配置正确进行单元测试
【发布时间】:2021-01-10 13:59:05
【问题描述】:

我有一个 dotnet-core 项目,它在启动过程中使用了很多依赖注入,这些依赖注入是用 ..Services.AddSingleton(someService) 之类的东西构建的。

如果我添加一个新服务并将它添加到其他消费服务的构造函数中,对它进行全部单元测试然后运行它,我会遇到 runtime 失败,因为我忘记添加新的服务到服务集合,它被注入为null

有没有办法对所有服务都正确配置并在运行时可用进行单元测试?


对于一些额外的上下文,在这个特定的时间里,我有一个 Azure Function App 和一个 aspnet-core Web 应用程序,它们都依赖于现有的服务。我修改了服务以依赖一个新的服务类,并使用构造函数注入来注入它。 Startup.cs 中的 DI 配置都运行时没有错误,但在运行时运行现有服务时,它失败并出现空引用错误,因为新的依赖项已被注入为空。 (是的,我应该在构造函数中有一个 null 保护,但即使这样仍然是运行时失败)。


我确定我在某个地方看到过这样做,但不记得在哪里。

【问题讨论】:

  • 向我建议的一个选项是使用集成测试来运行整个应用程序,也许只是在 CI 中,这也可以发现任何 DI 问题。
  • DI验证是一个很大的话题manydifferentviews。也就是说,在构建服务提供者时使用VerifyOnBuild 是一个开始。

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


【解决方案1】:

我们可以使用ServiceCollection容器来测试注册。

private static bool ServiceRegistered(IServiceCollection serviceCollection, Type serviceType, ServiceLifetime serviceLifetime)
{
     if (serviceCollection == null)
     {
         return false;
     }

     var serviceDescriptors = serviceCollection.GetEnumerator();

     if (serviceDescriptors == null)
     {
         return false;
     }

     while (serviceDescriptors.MoveNext())
     {
         var current = serviceDescriptors.Current;

         if (current.Lifetime == serviceLifetime && current.ServiceType == serviceType)
         {
             return true;
         }
     }

     return false;
    }

那我们就可以测试了

using Xunit;
using FluentAssertions;

[InlineData(typeof(IService), ServiceLifetime.Transient)]
public void ServiceRegistrationTest(Type serviceType, ServiceLifetime serviceLifetime)
{
    IServiceCollection services = new ServiceCollection();
        
    services.RegisterServices();

    bool registeredServiceLifetime = ServiceRegistered(services, serviceType, serviceLifetime);
    registeredServiceLifetime.Should().BeTrue();
}

【讨论】:

  • 您介意添加更多解释吗?我不完全确定它在测试什么。如果无法实例化任何服务类,那会失败吗?
  • 我得到了上面的编译,如下所示:gist.github.com/timabell/7ea8767e4151a56708ab0335f37696d4 但它没有通过,因为测试缺少真正服务需要实例化的所有环境和配置,所以我没有看不到测试实际上做了什么。这确实引发了服务已配置并且测试项目无权访问该配置的问题,这是我之前没有考虑过的。
  • 嗨,蒂姆,服务的测试配置可能需要您拆分到小的上下文,然后用户可以限制测试的范围。我的示例是关于测试服务生命周期的。当您想测试具有所有环境和配置的服务时,如果您可以尝试使用 Moq 模拟配置,并尽可能尝试多种情况,当您想测试并查看应用程序将如何运行时,我认为会更好由于它是实时的,您可以查看 SUT 测试:docs.microsoft.com/en-us/aspnet/core/test/…
猜你喜欢
  • 2017-07-28
  • 2010-09-23
  • 1970-01-01
  • 2017-01-13
  • 1970-01-01
  • 2014-01-28
  • 1970-01-01
  • 2023-03-20
相关资源
最近更新 更多