I’m currently working on moving a large legacy system from .NET Framework 4.8 to .NET 6. Since this is a large system the move will take years and we need to work iteratively meaning both systems will co-exist over a few years.
This means that integration tests we already have for the legacy system now needs to execute code over two application domains running two completely different CLRs. I ended up making a little service that the legacy code can call to execute code in the new system.
First we create a new web API project with a single controller.
[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{
private static readonly Dictionary<Guid, IServiceProvider> ServiceProviders = new();
public bool Get()
{
return true;
}
[HttpPost("SetupTest")]
public async Task SetupTest(Guid testId, string connectionString)
{
var collection = new ServiceCollection();
var provider = collection
.AddCqs(configure => collection.AddMassTransitTestHarness(cfg =>
{
cfg.UsingInMemory((ctx, mem) =>
{
mem.ConfigureTestHarness(ctx);
mem.AddOutbox(ctx);
mem.ConfigureEndpoints(ctx);
});
configure(cfg);
}))
.AddDbContext<PcDbContext>(b =>
{
b.UseSqlServer(connectionString);
})
.AddBusinessCore()
.AddRepositories()
.AddDomain()
.AddTestHarness()
.AddTestGuidFileRepository()
.BuildServiceProvider();
var harness = provider.GetRequiredService<IHarness>();
await harness.Start();
ServiceProviders.Add(testId, provider);
}
[HttpPost("TeardownTest")]
public void TeardownTest(Guid testId)
{
ServiceProviders.Remove(testId);
}
private static readonly JsonSerializerOptions Options = new() { PropertyNameCaseInsensitive = true };
[HttpPost("ExecuteCommand")]
public async Task ExecuteCommand(Guid testId, string cmdType)
{
var provider = ServiceProviders[testId];
var cmd = (await JsonSerializer.DeserializeAsync(HttpContext.Request.Body, Type.GetType(cmdType)!, Options))!;
await provider.GetRequiredService<IBus>().Publish(cmd);
await provider.GetRequiredService<IHarness>().WaitForBus();
}
}
(more…)