fix: test infrastructure with in-memory DB, SMTP mocking, and thread-safe billing configuration
- Add in-memory database support for test isolation in WebServerFixture - Implement TestMailSender fake SMTP provider for email test support - Add thread synchronization to billing service registration to prevent race conditions - Make RegisterBilling<T> idempotent to safely handle reconfiguration - Configure test environment via in-memory settings (UseTestEmailSender, UseInMemoryDatabase) - Add regression tests for billing module idempotency and duplicate registration detection - Fix tests: EMaillingTests.SendEMailSynchrone, BillingServiceTests (2 tests), HaveConfigurationRoot (3 tests) All core test infrastructure tests now passing.
This commit is contained in:
parent
be7df3d054
commit
87d62791b8
10 changed files with 223 additions and 58 deletions
|
|
@ -99,9 +99,20 @@ public static class HostingExtensions
|
|||
options.ResourcesPath = "Resources";
|
||||
}).AddDataAnnotationsLocalization();
|
||||
|
||||
services.AddTransient<ITrueEmailSender, MailSender>()
|
||||
.AddTransient<Microsoft.AspNetCore.Identity.UI.Services.IEmailSender, MailSender>()
|
||||
.AddTransient<IYavscMessageSender, YavscMessageSender>()
|
||||
bool useTestEmailSender = builder.Configuration.GetValue<bool>("UseTestEmailSender", false);
|
||||
|
||||
if (useTestEmailSender)
|
||||
{
|
||||
services.AddTransient<ITrueEmailSender, TestMailSender>()
|
||||
.AddTransient<Microsoft.AspNetCore.Identity.UI.Services.IEmailSender, TestMailSender>();
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddTransient<ITrueEmailSender, MailSender>()
|
||||
.AddTransient<Microsoft.AspNetCore.Identity.UI.Services.IEmailSender, MailSender>();
|
||||
}
|
||||
|
||||
services.AddTransient<IYavscMessageSender, YavscMessageSender>()
|
||||
.AddTransient<IBillingService, BillingService>()
|
||||
.AddTransient<IDataStore, FileDataStore>((sp) => new FileDataStore("googledatastore", false))
|
||||
.AddTransient<ICalendarManager, CalendarManager>()
|
||||
|
|
@ -150,11 +161,21 @@ public static class HostingExtensions
|
|||
public static IdentityBuilder AddIdentityDBAndStores(this WebApplicationBuilder builder)
|
||||
{
|
||||
IServiceCollection services = builder.Services;
|
||||
services.AddDbContext<ApplicationDbContext>(options =>
|
||||
bool useInMemory = builder.Configuration.GetValue<bool>("UseInMemoryDatabase", false);
|
||||
|
||||
if (useInMemory)
|
||||
{
|
||||
options.UseNpgsql(builder.Configuration.GetConnectionString(Constants.YavscConnectionStringName),
|
||||
options => options.MigrationsAssembly(typeof(Program).Assembly));
|
||||
});
|
||||
services.AddDbContext<ApplicationDbContext>(options =>
|
||||
options.UseInMemoryDatabase("YavscInMemory"));
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddDbContext<ApplicationDbContext>(options =>
|
||||
{
|
||||
options.UseNpgsql(builder.Configuration.GetConnectionString(Constants.YavscConnectionStringName),
|
||||
options => options.MigrationsAssembly(typeof(Program).Assembly));
|
||||
});
|
||||
}
|
||||
|
||||
return services.AddIdentity<ApplicationUser, IdentityRole>(
|
||||
options =>
|
||||
|
|
@ -269,6 +290,8 @@ public static class HostingExtensions
|
|||
});
|
||||
var migrationsAssembly = typeof(Program).GetTypeInfo().Assembly.GetName().Name;
|
||||
var connectionString = builder.Configuration.GetConnectionString(Constants.YavscConnectionStringName);
|
||||
bool useInMemory = builder.Configuration.GetValue<bool>("UseInMemoryDatabase", false);
|
||||
string inMemoryDatabaseName = "YavscInMemory";
|
||||
|
||||
var identityServerBuilder = builder.Services.AddIdentityServer(options =>
|
||||
{
|
||||
|
|
@ -288,26 +311,40 @@ public static class HostingExtensions
|
|||
.AddResourceStore<ResourceStore>()
|
||||
.AddConfigurationStore(options =>
|
||||
{
|
||||
options.ConfigureDbContext = b => b.UseNpgsql(connectionString,
|
||||
sql => sql.MigrationsAssembly(migrationsAssembly))
|
||||
.UseSeeding((context, _) =>
|
||||
{
|
||||
foreach (String scope in new string[] { "blog", "admin", "contract", "com"})
|
||||
{
|
||||
var testBlog = context.Set<ApiScope>().FirstOrDefault(b => b.Name == scope);
|
||||
if (testBlog == null)
|
||||
if (useInMemory)
|
||||
{
|
||||
context.Set<ApiScope>().Add(new ApiScope { Name = scope });
|
||||
context.SaveChanges();
|
||||
options.ConfigureDbContext = b => b.UseInMemoryDatabase(inMemoryDatabaseName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
options.ConfigureDbContext = b => b.UseNpgsql(connectionString,
|
||||
sql => sql.MigrationsAssembly(migrationsAssembly))
|
||||
.UseSeeding((context, _) =>
|
||||
{
|
||||
foreach (String scope in new string[] { "blog", "admin", "contract", "com"})
|
||||
{
|
||||
var testBlog = context.Set<ApiScope>().FirstOrDefault(b => b.Name == scope);
|
||||
if (testBlog == null)
|
||||
{
|
||||
context.Set<ApiScope>().Add(new ApiScope { Name = scope });
|
||||
context.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
||||
.AddOperationalStore(options =>
|
||||
{
|
||||
options.ConfigureDbContext = b => b.UseNpgsql(connectionString,
|
||||
sql => sql.MigrationsAssembly(migrationsAssembly));
|
||||
if (useInMemory)
|
||||
{
|
||||
options.ConfigureDbContext = b => b.UseInMemoryDatabase(inMemoryDatabaseName);
|
||||
}
|
||||
else
|
||||
{
|
||||
options.ConfigureDbContext = b => b.UseNpgsql(connectionString,
|
||||
sql => sql.MigrationsAssembly(migrationsAssembly));
|
||||
}
|
||||
});
|
||||
|
||||
if (builder.Environment.IsDevelopment())
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" />
|
||||
<PackageReference Include="Google.Apis.Compute.v1" />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue