Asp.Net Core 与 CustomWebApplicationFactory 集成测试 - 它是如何工作的?

问题描述 投票:0回答:1

为了更好地理解集成测试,我使用

IClassFixture<T>
(来自https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2#使用默认 webapplicationfactory 进行基本测试)。

这对于测试诸如页面加载、表单显示、获取正确的 http 状态代码等非常有用。但是在测试 API 时,您将需要一些种子数据。这样做的典型方法是 EF 内存数据库。这是通过自定义 Web 应用程序工厂实现的,您可以在其中创建范围、请求适当的服务(即 dbcontext)并为其提供种子(例如 https://learn.microsoft.com/en-us/aspnet/core/测试/集成测试?view=aspnetcore-2.2#customize-webapplicationfactory)。

我有一个正在运行且功能齐全的集成测试项目。但它的工作原理的细微差别仍然让我感到困惑。


我是否正确地假设,当您创建CustomWebApplicationFactory时,本质上您正在创建一个自定义“Program.cs”(即应用程序的典型入口点),您可以根据需要自由添加其他测试服务/过滤器?


这是我用于集成测试的 Web 应用程序工厂的实现。我的 API 对大多数端点都有基本身份验证,因此我添加了一个全局过滤器来绕过它。但我下面所做的基本上与我的实际 API 中的 Program.cs 相同(唯一的区别是我没有添加假用户和全局匿名过滤器)。所以我相信我的上述观点是正确的。这是一个正确的假设吗?

我想验证的另一点是,在实际的单元测试中,我可以用模拟替换服务。这在集成测试中是否可能,我可以将所请求的服务的 DI 实例替换为测试服务?


例如我的应用程序有
IUploadFileToAzure
服务。我可以在集成测试中使用
TestUploadFileToAzure
服务替换该实现,而不是使用 UploadFileToAzure 作为 DI 实例吗?


多次注册服务会占用最后一次注册服务的时间,因此我想知道这是否可以用作上述观点的解决方法。这还推荐吗?我知道这违背了测试服务的目的,但想验证这是否可行。我尝试在本地进行测试,但没有成功。

public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<Startup>
    {
        protected override IWebHostBuilder CreateWebHostBuilder()
        {
            return WebHost
                .CreateDefaultBuilder<Startup>(new string[0])
                .ConfigureServices(services =>
                {
                    services.AddSingleton<IStartupFilter, AddCustomMiddlewareStartupFilter>();
                });
        }

       
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {
            builder
            .UseEnvironment("Development")
            .ConfigureServices(services =>
            {
                services.AddMvc(opt =>
                {
                    //add a global anonymous filter
                    opt.Filters.Add(new AllowAnonymousFilter());

                    //add a filter for adding a fake claimsprincipal so that the user service
                    //correctly identifies the user
                    opt.Filters.Add(new FakeClaimsPrincipalFilter(true, false));
                });

                services.AddEntityFrameworkInMemoryDatabase();

                // Create a new service provider.
                var provider = services
                    .AddEntityFrameworkInMemoryDatabase()
                    .BuildServiceProvider();

                // Add a database context using an in-memory 
                // database for testing.
                services.AddDbContext<AppDbContext>(options =>
                {
                    options.UseInMemoryDatabase("TestDb");
                    options.UseInternalServiceProvider(provider);
                });
    
                // Build the service provider.
                var sp = services.BuildServiceProvider();

                // Create a scope to obtain a reference to the database context 
                using (var scope = sp.CreateScope())
                {
                    var scopedServices = scope.ServiceProvider;
                    var apiDb = scopedServices.GetRequiredService<AppDbContext>();   

                    // Ensure the database is created.
                    apiDb.Database.EnsureCreated();
                }
            });
        }
    }
c# asp.net-core
1个回答
4
投票

我假设当你创建一个 CustomWebApplicationFactory,本质上您正在创建一个自定义 “Program.cs”(即应用程序的典型入口点),其中 您可以根据需要自由添加额外的测试服务/过滤器吗?

是的,你说得对。对于

Program.cs
它将创建真实的主机服务器。对于
CustomWebApplicationFactory
,它将为集成测试创建
TestServer

我的应用程序有 IUploadFileToAzure 服务。而不是使用 UploadFileToAzure 作为 DI 实例,我可以替换它吗 在我的集成中使用 TestUploadFileToAzure 服务实现 测试?

要替换现有服务,您可以尝试

ConfigureTestServices
并且可以参考注入模拟服务

© www.soinside.com 2019 - 2024. All rights reserved.