C# 如何覆盖在某些测试中使用IWebHostBuilder.ConfigureTestServices模拟的服务

C# 如何覆盖在某些测试中使用IWebHostBuilder.ConfigureTestServices模拟的服务,c#,asp.net-core,.net-core,integration-testing,C#,Asp.net Core,.net Core,Integration Testing,我有一个定制的WebApplicationFactory,为此我模拟了一些用于集成测试的服务,如DatabaseSeeder,以使测试运行得更快 现在我想测试数据库种子设定,所以我想覆盖配置,以便在测试中使用真正的数据库种子设定器 我尝试在WebHostBuilder中使用,它返回一个新的WebApplicationFactory,但是这个新工厂中的builder.ConfigureTestServices方法在原始工厂之前运行,因此它被原始工厂覆盖ConfigureTestServices

我有一个定制的
WebApplicationFactory
,为此我模拟了一些用于集成测试的服务,如
DatabaseSeeder
,以使测试运行得更快

现在我想测试数据库种子设定,所以我想覆盖配置,以便在测试中使用真正的数据库种子设定器

我尝试在WebHostBuilder中使用
,它返回一个新的
WebApplicationFactory
,但是这个新工厂中的
builder.ConfigureTestServices
方法在原始工厂之前运行,因此它被原始工厂覆盖
ConfigureTestServices

  /// <summary>
    /// custom web application factory for testing.
    /// </summary>
    public class LwtTestWebApplicationFactory : WebApplicationFactory<Startup>
    {
        ....

        /// <inheritdoc />
        protected override void ConfigureWebHost(IWebHostBuilder builder)
        {
            builder.ConfigureTestServices(
                services =>
                {
                    // Replace database seeder.
                    ServiceDescriptor databaseSeederDescriptor =
                        services.Single(s => s.ServiceType == typeof(IDatabaseSeeder));

                    services.Remove(databaseSeederDescriptor);

                    var mock = new Mock<IDatabaseSeeder>();
                    mock.Setup(s => s.SeedData())
                        .Returns(Task.CompletedTask);
                    services.AddTransient(resolver => mock.Object);

                    // Replace index creator.
                    ServiceDescriptor indexCreatorDescriptor =
                        services.Single(s => s.ServiceType == typeof(IIndexCreator));

                    services.Remove(indexCreatorDescriptor);

                    var indexCreatorMock = new Mock<IIndexCreator>();
                    indexCreatorMock.Setup(s => s.CreateIndexesAsync())
                        .Returns(Task.CompletedTask);
                    services.AddTransient(resolver => indexCreatorMock.Object);

                    // Remove the app's ApplicationDbContext registration.
                    ServiceDescriptor descriptor = services.SingleOrDefault(
                        d => d.ServiceType == typeof(DbContextOptions<IdentityDbContext>));

                    if (descriptor != null)
                    {
                        services.Remove(descriptor);
                    }

                    // Add ApplicationDbContext using an in-memory database for testing.
                    services.AddDbContext<IdentityDbContext>(
                        (options, context) => { context.UseInMemoryDatabase("InMemoryDbForTesting"); });

                    ServiceDescriptor appSettingDescriptor = services.SingleOrDefault(
                        d => d.ServiceType == typeof(AppSettings));

                    if (appSettingDescriptor != null)
                    {
                        var appSetting = (AppSettings)appSettingDescriptor.ImplementationInstance;
                        services.Remove(appSettingDescriptor);
                        services.AddSingleton(
                            new AppSettings
                            {
                                MongoDatabase = appSetting.MongoDatabase,
                                Secret = appSetting.Secret,
                                MongoConnectionString = this.mongoDbRunner.ConnectionString,
                            });
                    }
                });
        }

        .....
    }
}
//
///用于测试的自定义web应用程序工厂。
/// 
公共类LWTetSetWebApplicationFactory:WebApplicationFactory
{
....
/// 
受保护的覆盖无效配置WebHost(IWebHostBuilder)
{
builder.ConfigureTestServices(
服务=>
{
//更换数据库播种器。
ServiceDescriptor数据库种子描述符=
单一(s=>s.ServiceType==typeof(IDatabaseSeeder));
删除(databaseSeederDescriptor);
var mock=new mock();
mock.Setup(s=>s.SeedData())
.Returns(Task.CompletedTask);
AddTransient(解析器=>mock.Object);
//替换索引创建者。
ServiceDescriptor索引描述器=
单一(s=>s.ServiceType==typeof(IIndexCreator));
服务。删除(indexCreatorDescriptor);
var indexCreatorMock=new Mock();
设置(s=>s.CreateIndexesAsync())
.Returns(Task.CompletedTask);
AddTransient(解析器=>indexCreatorMock.Object);
//删除应用程序的ApplicationDbContext注册。
ServiceDescriptor描述符=services.SingleOrDefault(
d=>d.ServiceType==typeof(DbContextOptions));
if(描述符!=null)
{
删除(描述符);
}
//使用内存中的数据库添加ApplicationDbContext以进行测试。
services.AddDbContext(
(选项,上下文)=>{context.UseInMemoryDatabase(“InMemoryDbForTesting”);};
ServiceDescriptor appSettingDescriptor=services.SingleOrDefault(
d=>d.ServiceType==typeof(AppSettings));
if(appSettingDescriptor!=null)
{
var appSetting=(AppSettings)appSettingDescriptor.ImplementationInstance;
删除(appSettingDescriptor);
服务.AddSingleton(
新应用程序设置
{
MongoDatabase=appSetting.MongoDatabase,
Secret=appSetting.Secret,
MongoConnectionString=this.mongoDbRunner.ConnectionString,
});
}
});
}
.....
}
}
我试过的

    using (var factory = new LwtTestWebApplicationFactory())
    using (WebApplicationFactory<Startup> seedEnabledFactory = factory.WithWebHostBuilder(
                builder =>
                {
                    builder.ConfigureTestServices(
                        services =>
                        {
                            // Replace database seeder.
                            ServiceDescriptor databaseSeederDescriptor =
                                services.Single(s => s.ServiceType == typeof(IDatabaseSeeder));

                            services.Remove(databaseSeederDescriptor);

                            services.AddTransient<IDatabaseSeeder, DatabaseSeeder>();

                            // Replace index creator.
                            ServiceDescriptor indexCreatorDescriptor =
                                services.Single(s => s.ServiceType == typeof(IIndexCreator));

                            services.Remove(indexCreatorDescriptor);

                            services.AddTransient<IIndexCreator, MongoDbIndexCreator>();
                        });
                }))
使用(var factory=new lwtsettwebaplicationfactory())
使用(WebApplicationFactory-seedEnabledFactory=factory.WithWebHostBuilder)(
生成器=>
{
builder.ConfigureTestServices(
服务=>
{
//更换数据库播种器。
ServiceDescriptor数据库种子描述符=
单一(s=>s.ServiceType==typeof(IDatabaseSeeder));
删除(databaseSeederDescriptor);
services.AddTransient();
//替换索引创建者。
ServiceDescriptor索引描述器=
单一(s=>s.ServiceType==typeof(IIndexCreator));
服务。删除(indexCreatorDescriptor);
services.AddTransient();
});
}))

我有同样的任务-在测试方法中本地重写某些服务,理想情况下不必每次都重建容器:

[事实]
公共异步任务GetSampleValue_当CalledWithMock_ReturnsMockValue()时
{
使用var mockServiceScope=\u testHostServiceProvider.CreateScope(mockServices=>
{
var mockSampleService=Substitute.For();
mockSampleService.GetSampleValue().ReturnsForAnyArgs(“模拟值”);
mockServices.AddSingleton(=>mockSampleService);
});
var sampleController=RestClient.For(_testHost.HttpClient);
var sampleValue=await sampleController.GetSampleValue();
Assert.Equal(“模拟值”,sampleValue);
}
我在一个库中实现了这个功能。也许,它会帮助你