C# 使用iLogger提供程序进行单元测试
我的单元测试设置中有如下代码:C# 使用iLogger提供程序进行单元测试,c#,asp.net-core,.net-core,asp.net-core-3.1,C#,Asp.net Core,.net Core,Asp.net Core 3.1,我的单元测试设置中有如下代码: IServiceCollection services = new ServiceCollection(); services.AddSingleton<IDependency, Dependency>(); services.AddLogging(); services.RemoveAll<ILoggerProvider>(); services.AddSingleton<ILoggerProvider, MyCustomProvi
IServiceCollection services = new ServiceCollection();
services.AddSingleton<IDependency, Dependency>();
services.AddLogging();
services.RemoveAll<ILoggerProvider>();
services.AddSingleton<ILoggerProvider, MyCustomProvider>(provider =>
{
var myDependency = provider.GetService<IDependency>();
return new MyCustomProvider(myDependency );
});
var serviceProvider = services.BuildServiceProvider();
var logger = serviceProvider.GetService<ILogger>();
不知何故,这是在不指明任何提供者的情况下完成的。我希望在我的单元测试中也能做到这一点。(只需使用我的自定义提供程序。)NET CORE测试我正在这样做: 在测试类的构造函数中(或进行DI映射的位置)
公共类UnitTest1
{
公共IConfigurationRoot配置{get;set;}
私有只读IDisponabilitaService_disponabilitaService;
公共单元测试1()
{
var services=newservicecolection();
配置=新的ConfigurationBuilder()
.SetBasePath(Path.Combine(Path.directoryseportorchar.ToString(),“directory”,“Kalliope_CTI”,“backend”,“KalliopeCTITestProject”))
.AddJsonFile(“testconfig.json”,可选:false,reloadOnChange:true)
.Build();
services.AddSingleton();//<--此处尝试设置NullLoggerFactory
var serviceProvider=服务
.AddOptions()
.BuildServiceProvider();
}
////你的测试方法
}
希望它能帮助你 它可能是在黑暗中拍摄的,但您可以尝试将您的
iLogger提供程序添加到iLogger工厂
:
var loggerFactory=serviceProvider.GetService示例中的logger
变量为null
的原因是ILogger
实际上没有注册为服务。如果查看AddLogging
的源代码,您可以看到它只注册了ILogger
和ILogger工厂
。如果您曾经尝试通过.NET Core DI接受ILogger
而不是ILogger
,您将遇到以下异常*:
System.InvalidOperationException:'无法解析类型的服务
“Microsoft.Extensions.Logging.ILogger”正在尝试激活
“你的服务”
基于此,您的测试代码是有缺陷的,因为您从一开始就不会收到ILogger
。要查看您的代码是否实际工作,请修改您的测试代码,使其检索ILogger
。变量的结果将为非null,并且将命中提供程序构造函数中设置的断点:
// Get*Required*Service won't throw
var logger = serviceProvider.GetRequiredService<ILogger<Program>>();
以下内容现在可以使用您的自定义提供程序:
var loggerA = serviceProvider.GetRequiredService<ILogger<Program>>();
var loggerB = serviceProvider.GetRequiredService<ILogger>();
var loggerA=serviceProvider.GetRequiredService();
var loggerB=serviceProvider.GetRequiredService();
我有自己的自定义提供程序/工厂/记录器,用于按照与您相同的注册模式将xUnit的ITestOutputHelper
注入自定义记录器,因此我根据个人经验知道这是可行的。但我还测试了您的特定代码是否正常工作(模拟我自己的IDependency
)——执行上述代码,并在MyCustomProvider
的构造函数中设置断点,然后点击服务注册。此外,如果我将记录器注入到一个类中,它也会被命中(正如预期的那样)
您的评论“不知何故,这是在没有指明任何提供商的情况下完成的”是错误的,因为您确实注册了提供商!但是,即使在清除了所有提供程序并且没有添加新的提供程序的场景中,您仍然会得到一个非空的记录器。这是因为LoggerFactory
只是循环遍历每个提供程序,围绕它们构建一个新的记录器包装器。如果没有提供程序,那么您基本上会得到一个无操作记录器
*这是不幸的,因为一些工具(如R#)会建议将参数转换为基本类型ILogger
,这会破坏DI
**默认类别名称是必需的,因为没有要传递给ILoggerFactory.CreateLogger
的泛型类型参数。对于通用的ILogger
来说,类别名称总是T
名称的一个变体——但我们显然没有在非通用版本中得到这一点。如果非要我猜的话,这可能就是为什么默认情况下他们不注册ILogger
的实现。hi您是否尝试过类似services.AddSingleton()的东西;
// Get*Required*Service won't throw
var logger = serviceProvider.GetRequiredService<ILogger<Program>>();
services.AddSingleton<ILoggerProvider, MyCustomProvider>(); // no need for lambda
services.AddSingleton<ILogger>(sp =>
sp.GetService<ILoggerFactory>().CreateLogger("Default")
);
var loggerA = serviceProvider.GetRequiredService<ILogger<Program>>();
var loggerB = serviceProvider.GetRequiredService<ILogger>();