102 lines
3.9 KiB
C#
102 lines
3.9 KiB
C#
using Gpulse.WCT.DataAnalyzer.Core.Infrastructure.Extensions;
|
|
using Gpulse.WCT.DataAnalyzer.Core.Infrastructure.LocalData;
|
|
using Microsoft.Data.Sqlite;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
namespace Gpulse.WCT.DataAnalyzer.Tests;
|
|
|
|
/// <summary>
|
|
/// CLI 测试宿主:用内存 SQLite 搭建与 Program.Main 一致的服务容器。
|
|
/// 每个测试实例持有独立的「本地库」/「发布库」连接与一个临时目录,互不污染。
|
|
/// </summary>
|
|
public sealed class CliTestHost : IDisposable
|
|
{
|
|
private readonly SqliteConnection _localConnection;
|
|
private readonly SqliteConnection _releaseConnection;
|
|
private readonly ServiceProvider _provider;
|
|
private readonly IServiceScope _scope;
|
|
|
|
/// <summary>测试作用域的服务提供者(与命令执行共用同一作用域)。</summary>
|
|
public IServiceProvider Services => _scope.ServiceProvider;
|
|
|
|
/// <summary>每个测试独立的临时目录,用于放置日志 fixture 文件。</summary>
|
|
public string TempDir { get; }
|
|
|
|
public WctMinerDbContext LocalDb => Services.GetRequiredService<WctMinerDbContext>();
|
|
public ReleaseDbContext ReleaseDb => Services.GetRequiredService<ReleaseDbContext>();
|
|
|
|
private CliTestHost(
|
|
SqliteConnection localConnection,
|
|
SqliteConnection releaseConnection,
|
|
ServiceProvider provider,
|
|
IServiceScope scope,
|
|
string tempDir)
|
|
{
|
|
_localConnection = localConnection;
|
|
_releaseConnection = releaseConnection;
|
|
_provider = provider;
|
|
_scope = scope;
|
|
TempDir = tempDir;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 创建测试宿主:本地库/发布库各用一条独立的内存 SQLite 连接(镜像生产环境的两个库文件),
|
|
/// 并做 EnsureCreated 与种子数据初始化。
|
|
/// </summary>
|
|
public static async Task<CliTestHost> CreateAsync()
|
|
{
|
|
var tempDir = Directory.CreateTempSubdirectory("wct-tests-").FullName;
|
|
|
|
// 两个库各自独立连接,避免共享连接时 EnsureCreated 相互干扰
|
|
var localConnection = new SqliteConnection("Data Source=:memory:");
|
|
await localConnection.OpenAsync();
|
|
|
|
var releaseConnection = new SqliteConnection("Data Source=:memory:");
|
|
await releaseConnection.OpenAsync();
|
|
|
|
var configuration = new ConfigurationBuilder()
|
|
.AddInMemoryCollection(new Dictionary<string, string?>
|
|
{
|
|
["Database:Type"] = "sqlite",
|
|
["Parser:BatchSize"] = "1000",
|
|
})
|
|
.Build();
|
|
|
|
var services = new ServiceCollection();
|
|
services.AddSingleton<IConfiguration>(configuration);
|
|
services.AddLogging();
|
|
services.AddDbContext<WctMinerDbContext>(o => o.UseSqlite(localConnection));
|
|
services.AddDbContext<ReleaseDbContext>(o => o.UseSqlite(releaseConnection));
|
|
services.AddApplicationServices();
|
|
|
|
var provider = services.BuildServiceProvider();
|
|
|
|
// 初始化表结构与种子数据(与 Program.Main 一致)
|
|
using (var scope = provider.CreateScope())
|
|
{
|
|
var local = scope.ServiceProvider.GetRequiredService<WctMinerDbContext>();
|
|
await local.Database.EnsureCreatedAsync();
|
|
SeedData.Initialize(local);
|
|
|
|
var release = scope.ServiceProvider.GetRequiredService<ReleaseDbContext>();
|
|
await release.Database.EnsureCreatedAsync();
|
|
}
|
|
|
|
var hostScope = provider.CreateScope();
|
|
return new CliTestHost(localConnection, releaseConnection, provider, hostScope, tempDir);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_scope.Dispose();
|
|
_provider.Dispose();
|
|
_localConnection.Dispose();
|
|
_releaseConnection.Dispose();
|
|
|
|
try { Directory.Delete(TempDir, recursive: true); }
|
|
catch { /* 尽力清理临时目录 */ }
|
|
}
|
|
}
|