我的注册和构造函数设置为通过Microsoft.Extensions使用日志记录。如下所示,
public MyService(ILogger<MyService> logger) {}
不过,我想做的是在Startup.cs中使用services.AddSingleton()
,以避免使用构造函数注入。原因是在测试服务时,它将需要修改所有单元测试以模拟记录器
我相信有一种方法可以在ServiceCollection中注册ILogger的特定实例,但我无法整理所需的语法。
谢谢!
- 在单元测试中,您不应该使用DI容器。
- 如果是,那么您正在编写集成测试,而不是单元测试
- 一般来说,在单元测试中,测试的arrange部分应该通过直接调用SUT的构造函数并传入其依赖关系的test/mok/stub版本来设置SUT
- 在单元测试中,理想情况下,您应该提供整个
Microsoft.Extensions.Logging.ILoggerProvider
接口(和相关类(的完整测试实现,这将允许您断言特定的日志输出消息已写入,或者将ILogger
和ILogger<T>
输出重定向到测试自己的输出。- 不幸的是,这不是现成的(微软也不会发布自己的(,但有很多流行的库:
- https://github.com/martincostello/xunit-logging
- https://github.com/alefranz/MELT
- 不幸的是,这不是现成的(微软也不会发布自己的(,但有很多流行的库:
- 或者,如果您的测试不关心断言
ILogger
的使用,和/或如果您不希望SUT自己的日志输出写入测试输出,那么在arrange部分中使用NullLoggerFactory
或NullLogger<T>.Instance
来创建一个不执行任何操作的存根ILogger<T>
像这样:
using Microsoft.Extensions.Logging.Abstractions;
// [...]
[Fact]
public void MyService_should_do_something()
{
// Arrange:
IArbitraryDependency dep = new StubArbitraryDependency();
#if FULL_MOON_TONIGHT
ILogger<MyService> nullLogger = NullLoggerFactory.Instance.CreateLogger<MyService>();
#else
ILogger<MyService> nullLogger = NullLogger<MyService>.Instance();
#endif
MyService systemUnderTest = new MyService(
arbitraryDependency: dep,
logger : nullLogger
);
// Act:
systemUnderTest.DoSomething();
// Assert:
// [...]
}