人们如何对.NET Core 2应用程序中的Startup.cs类进行单元测试?所有功能似乎都是由静态扩展方法提供的,这些方法不是可模拟的吗?
如果以这种ConfigureServices
方法为例:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<BlogContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddMvc();
}
如何编写测试以确保调用AddDbContext(...)和AddMvc(),通过Extensions方法实现所有这些功能的选择似乎使其无法测试?
好吧,是的,如果您想检查AddDbContext
调用扩展方法的事实,services
您将遇到麻烦。好消息是您实际上不应该检查这个事实。
Startup
类是应用程序组合的根。并且,在测试组合根时,您需要检查它是否实际注册了实例化根对象所需的所有依赖关系(对于ASP.NET Core应用程序为控制器)。
假设您有以下控制器:
public class TestController : Controller
{
public TestController(ISomeDependency dependency)
{
}
}
您可以尝试检查是否Startup
已注册的类型ISomeDependency
。但是实施ISomeDependency
可能还需要检查其他一些依赖项。最终,您最终得到一个测试,该测试要对大量依赖项进行大量检查,但实际上并不能保证对象解析不会抛出缺少的依赖项异常。这样的测试没有太大的价值。
在测试合成根时,一种对我来说很好的方法是使用真实的依赖注入容器。然后,我在其上调用合成根,并断言不会抛出根对象的分辨率。
由于我们使用其他非存根类,因此不能将其视为纯单元测试。但是,与其他集成测试不同,此类测试快速且稳定。最重要的是,它们带来了有效检查的价值,用于正确的依赖项注册。如果这样的测试通过,则可以确定该对象也将在产品中正确实例化。
这是此类测试的示例:
[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);
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句