Использование ILogger<T> без внедрения конструктора
У меня есть настройка регистрации и конструктора для использования ведения журнала через Microsoft.Extensions.Logging следующим образом:
public MyService(ILogger<MyService> logger) {}
Однако я хотел бы использовать
services.AddSingleton()
в моем Startup.cs, чтобы избежать использования внедрения конструктора. Причина в том, что в противном случае потребуется изменить все модульные тесты, чтобы имитировать регистратор при тестировании службы.
Я считаю, что есть способ зарегистрировать конкретный экземпляр ILogger в ServiceCollection, но я не могу разобраться с необходимым синтаксисом.
Спасибо!
1 ответ
- В модульных тестах вы не должны использовать DI-контейнер.
- Если да, то вы пишете интеграционный тест, а не модульный тест.
- В модульных тестах, вообще говоря, организационная часть теста должна настроить вашу SUT, напрямую вызывая конструктор SUT и передавая версии test/mock/stub его зависимостей.
- В модульных тестах в идеале вы должны предоставить полную тестовую реализацию всего
Microsoft.Extensions.Logging.ILoggerProvider
интерфейс (и связанные классы), который позволит вам утверждать, что определенные выходные сообщения журнала были записаны, или перенаправлять и выводить на собственный вывод вашего теста.- К сожалению, это не входит в комплект (и Microsoft не будет выпускать свои собственные ), но для этого есть много популярных библиотек:
- В качестве альтернативы, если ваши тесты не связаны с утверждением
ILogger
использования и/или если вы не хотите, чтобы собственный вывод журнала вашей SUT записывался в ваш тестовый вывод, используйте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:
// [...]
}