如何在.NET Core中对Startup.cs进行unit testing
人们如何在.NET Core 2应用程序中对其Startup.cs类进行unit testing? 所有function似乎都是由静态扩展方法提供的,这些方法不可模拟?
例如,如果您使用此ConfigureServices
方法:
public void ConfigureServices(IServiceCollection services) { services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddMvc(); }
如何编写测试以确保调用AddDbContext(…)和AddMvc(),通过Extensions方法实现所有这些function的选择似乎使其不可测试?
是的,如果你想检查在你遇到麻烦的services
调用扩展方法AddDbContext
的事实。 好的是你不应该真正检查这个事实。
Startup
类是应用程序组合根 。 在测试组合根时,您要检查它是否实际注册了实例化根对象(ASP.NET Core应用程序中的控制器)所需的所有依赖项。
假设您有以下控制器:
public class TestController : Controller { public TestController(ISomeDependency dependency) { } }
您可以尝试检查Startup
是否已注册ISomeDependency
的类型。 但是, ISomeDependency
实现还可能需要您应该检查的其他一些依赖项。 最终,您最终会得到一个针对不同依赖项进行大量检查的测试,但实际上并不能保证对象解析不会丢失缺少的依赖项exception。 这样的测试没有太多价值。
在测试组合根时,一种适合我的方法是使用真正的dependency injection容器。 然后我在其上调用一个组合根并断言根对象的解析不会抛出。
它不能被视为纯unit testing,因为我们使用其他非存根类。 但是,与其他集成测试不同,此类测试快速而稳定。 最重要的是,它们为正确的依赖注册带来了有效检查的价值。 如果此类测试通过,您可以确定该对象也将在产品中正确实例化。
以下是此类测试的示例:
[TestMethod] public void ConfigureServices_RegistersDependenciesCorrectly() { // Arrange // Setting up the stuff required for Configuration.GetConnectionString("DefaultConnection") Mock configurationSectionStub = new Mock (); configurationSectionStub.Setup(x => x["DefaultConnection"]).Returns("TestConnectionString"); Mock configurationStub = new Mock(); 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(); // Assert var serviceProvider = services.BuildServiceProvider(); var controller = serviceProvider.GetService (); Assert.IsNotNull(controller); }