如何在 .NET Core 中对 Startup.cs 进行单元测试

How to Unit Test Startup.cs in .NET Core(如何在 .NET Core 中对 Startup.cs 进行单元测试)
本文介绍了如何在 .NET Core 中对 Startup.cs 进行单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

人们如何在 .NET Core 2 应用程序中对他们的 Startup.cs 类进行单元测试?所有功能似乎都是由不可模拟的静态扩展方法提供的?

How do people go about Unit Testing their Startup.cs classes in a .NET Core 2 application? All of the functionality seems to be provided by Static extensions methods which aren't mockable?

如果你以这个 ConfigureServices 方法为例:

If you take this ConfigureServices method for example:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<BlogContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddMvc();
}

如何编写测试以确保 AddDbContext(...) &调用了 AddMvc(),通过 Extensions 方法实现所有这些功能的选择似乎使其无法测试?

How can I write tests to ensure that AddDbContext(...) & AddMvc() are called, The choice of implementing all of this functionality via Extensions methods seems to have made it untestable?

推荐答案

好吧,如果你想检查扩展方法 AddDbContextservices 上被调用的事实,你有麻烦了.好消息是您实际上不应该确切地检查这个事实.

Well yes, if you want to check the fact that extension method AddDbContext was called on services you are in trouble. The good thing is that you shouldn't actually check exactly this fact.

Startup 类是一个应用程序composition root.并且在测试组合根时,您希望检查它是否实际注册了根对象(在 ASP.NET Core 应用程序中为控制器)实例化所需的所有依赖项.

Startup class is an application composition root. And when testing a composition root you want to check that it actually registers all dependencies required for instantiation of the root objects (controllers in the case of ASP.NET Core application).

假设你有以下控制器:

public class TestController : Controller
{
    public TestController(ISomeDependency dependency)
    {
    }
}

您可以尝试检查 Startup 是否注册了 ISomeDependency 的类型.但是 ISomeDependency 的实现也可能需要您应该检查的其他一些依赖项.最终你会得到一个对不同依赖项进行大量检查的测试,但它实际上并不能保证对象解析不会抛出缺少依赖项异常.这样的测试没有太大的价值.

You could try checking whether Startup has registered the type for ISomeDependency. But implementation of ISomeDependency could also require some other dependencies that you should check. Eventually you end up with a test that has tons of checks for different dependencies but it does not actually guarantee that object resolution will not throw missing dependency exception. There is not too much value in such a test.

在测试组合根时对我来说效果很好的一种方法是使用真正的依赖注入容器.然后我调用它的组合根并断言根对象的分辨率不会抛出.

An approach that works well for me when testing a composition root is to use real dependency injection container. Then I call a composition root on it and assert that resolution of the root object does not throw.

它不能被视为纯单元测试,因为我们使用其他非存根类.但与其他集成测试不同,此类测试快速且稳定.最重要的是,它们为正确的依赖项注册带来了有效检查的价值.如果此类测试通过,您可以确定该对象也将在产品中正确实例化.

It could not be considered as pure Unit Test because we use other non-stubbed class. But such tests, unlike other integration tests, are fast and stable. And most important they bring the value of valid check for correct dependencies registration. If such test passes you could be sure that object will also be correctly instantiated in the product.

以下是此类测试的示例:

Here is a sample of such test:

[TestMethod]
public void ConfigureServices_RegistersDependenciesCorrectly()
{
    //  Arrange

    //  Setting up the stuff required for Configuration.GetConnectionString("DefaultConnection")
    Mock<IConfigurationSection> configurationSectionStub = new Mock<IConfigurationSection>();
    configurationSectionStub.Setup(x => x["DefaultConnection"]).Returns("TestConnectionString");
    Mock<Microsoft.Extensions.Configuration.IConfiguration> configurationStub = new Mock<Microsoft.Extensions.Configuration.IConfiguration>();
    configurationStub.Setup(x => x.GetSection("ConnectionStrings")).Returns(configurationSectionStub.Object);

    IServiceCollection services = new ServiceCollection();
    var target = new Startup(configurationStub.Object);

    //  Act

    target.ConfigureServices(services);
    //  Mimic internal asp.net core logic.
    services.AddTransient<TestController>();

    //  Assert

    var serviceProvider = services.BuildServiceProvider();

    var controller = serviceProvider.GetService<TestController>();
    Assert.IsNotNull(controller);
}

这篇关于如何在 .NET Core 中对 Startup.cs 进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

How to MOQ an Indexed property(如何最小起订量索引属性)
Mocking generic methods in Moq without specifying T(在 Moq 中模拟泛型方法而不指定 T)
How Moles Isolation framework is implemented?(Moles Isolation 框架是如何实现的?)
Difference between Dependency Injection and Mocking Framework (Ninject vs RhinoMocks or Moq)(依赖注入和模拟框架之间的区别(Ninject vs RhinoMocks 或 Moq))
How to mock Controller.User using moq(如何使用 moq 模拟 Controller.User)
How do I mock a class without an interface?(如何模拟没有接口的类?)