中介程序处理程序在集成测试请求时注册失败



我想使用TestServer对我的一个微服务执行集成测试。我使用默认的IoC容器来注册依赖项。我的启动是微服务启动的副本,没有数据库健康检查服务等。要注册Mediator处理程序,我使用:

var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(
x => x.FullName.Contains($"test.{type.ToString()}") || x.FullName.Contains($"test.Common")).ToArray();
services.AddMediatR(assemblies.GetAssemblies);

此外,我的AppTestFixture类看起来像:

public class AppTestFixture : WebApplicationFactory<TestStartup>
{
protected override IHostBuilder CreateHostBuilder()
{
var builder = Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<TestStartup>()
.UseTestServer();
});
return builder;
}
}

不幸的是,这段代码在实际生产中运行良好,这意味着Mediator处理程序已正确注册,但如果我执行集成测试,则会引发"未找到注册处理程序"异常。为什么处理程序在真实环境中正确注册,而在测试中却没有?如何在测试环境中注册MediatR处理程序?

本部分

var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(
x => x.FullName.Contains($"test.{type.ToString()}") || x.FullName.Contains($"test.Common")).ToArray();

在调试下运行一个单独的测试或管道输出以下内容:

AppDomain.CurrentDomain.GetAssemblies() 

我可以想象,在运行集成测试时,where子句都不适用,但如果没有更多信息,这很难说。当你运行测试时,看看输出是什么,这将是关键。

所以这个

services.AddMediatR(assemblies.GetAssemblies);

不注册处理程序,因为结果为null/空。

如果这并没有给您带来问题,那么您可以尝试手动注册最少的处理程序。然后,您可以查看是否是注册过程导致了问题。所以手动注册如下:

services.AddScoped(typeof(ISomeType), typeof(SomeType));

services.AddScoped<ISomeType, SomeType>();

如果你这样做,你至少从这个过程中拿走了GetAssemblies((中的任何反射内容。我总是尝试隔离单个测试并调试它。

希望这能帮助

我在使用MediatR时遇到这些问题的原因是,我有多个(两个(WebApplicationFactory在其中引发了完全相同的异常。

当我改变实例化的顺序时,它运行得很好——但这当然不重要——所以我深入了一点。

结果是,由于程序集是延迟加载到AppDomain(共享(中的,因此当应用程序需要更多程序集时,加载的程序集列表将增加。

在我的例子中,WebApplicationFactory A的列表包含IRequest类型及其相应的处理程序。当WebApplicationFactory B启动时,AddMediatR()调用失败,因为它找不到属于WebApplicationFactory A的IRequest类型的句柄。

由于我们的解决方案中项目的命名是一致的,我通过检查类型的名称来修复它,根据传递的泛型类型,它是否以相同的名称开始,如下所示:

private static IServiceCollection AddMediatR<T>(this IServiceCollection serviceCollection)
{
var manifestModuleName = typeof(T).Assembly.FullName;
var assemblyPattern = new Regex(@"(Organisation.(.*?)).");
var match = assemblyPattern.Match(manifestModuleName!);
if (!match.Success) return serviceCollection;
var assemblyName = match.Groups[1].Value;
var applicationAssemblies = AppDomain.CurrentDomain.GetAssemblies()
.Where(assembly => assembly.FullName != null && assembly.FullName.StartsWith(assemblyName))
.ToArray();
if (applicationAssemblies.Any())
{
serviceCollection.AddMediatR(applicationAssemblies);
}
return serviceCollection;
}

相关内容

  • 没有找到相关文章

最新更新