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…)