TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #2978 2.31K
День 2477. #ЗаметкиНаПолях
Тестирование с Использованием FakeLogger
Вместо того, чтобы заниматься сложными настройками моков или проверять вызовы вручную, FakeLogger собирает сообщения журнала, области действия и структурированные данные в памяти, делая утверждения простыми и выразительными. Сегодня рассмотрим, как тестировать области логирования с помощью FakeLogger, зачем нужны области и как использовать их в коде.

Зачем использовать области действия?
Область логирования в .NET позволяет прикреплять контекстную информацию ко всем записям журнала в блоке кода. Представьте себе облегчённый набор пар «ключ-значение», который дополняет сообщения журнала, не заставляя вас предоставлять одни и те же поля в каждую запись журнала.

Например, вы можете добавить идентификатор запроса, идентификатор корреляции или идентификатор сущности в область действия, тем самым предоставляя в каждую запись журнала в этом блоке одинаковые контекстные метаданные. Это значительно упрощает фильтрацию и анализ журналов в распределённых системах или при отладке конкретных запросов.

Использование FakeLogger с областями действия
Начнём с простого метода, использующего область действия журналирования:
public partial class 
DemoService(ILogger<DemoService> lgr)
{
public void LogMe(Guid id)
{
using var _ =
lgr.BeginScope(
new Dictionary<string, object> { { "id", id } });

lgr.LogInformation("Пишем в лог.");
}
}

Здесь вызов BeginScope создаёт контекст логирования с единственным ключом (id). При вызове lgr.LogInformation область действия автоматически включает эти контекстные данные. Но как это проверить в тесте?

FakeLogger отслеживает каждую запись журнала, включая шаблоны сообщений, уровни ведения журнала, исключения и области действия. Проверим, правильно ли DemoService пишет в лог, включая id:
public class DemoServiceTests
{
[Fact]
public void ScopeUsage()
{
var fakeLogger = new FakeLogger<DemoService>();
var sut = new DemoService(fakeLogger);
var id = Guid.NewGuid();

sut.LogMe(id);

fakeLogger
.LatestRecord
.Message
.Should()
.Be("Пишем в лог.");

var scope = fakeLogger
.LatestRecord
.Scopes[0] as Dictionary<string, object>;
scope.Should().NotBeNull();
scope.Keys.Should().Contain("id");
scope.Values.Should().Contain(id);
}
}

В этом тесте мы:
- Создаём экземпляр тестируемой системы (SUT), используя FakeLogger<DemoService>.
- Вызываем метод LogMe(), генерирующий одну запись журнала.
- Проверяем содержимое сообщения и проверяем, записана ли коллекция из области действия.

Каждая область действия регистрируется как объект, и в данном случае это Dictionary<string, object>, содержащий id. Этот подход понятен, выразителен и поддерживается фреймворком, устраняя необходимость в пользовательских оболочках для логирования или ненадёжных настройках верификации моков.

Недостаток в том, что вам, вероятно, потребуется знать, как использовалась область действия в коде, чтобы тесты проверяли то, что вам нужно, однако в данном контексте это приемлемо.

Источник: https://adamstorr.co.uk/blog/testing-with-fakelogger-scopes/
  • 👍 8
More from @netdeveloperdiary
  1. Sep 30, 2026Post #3356
  2. Sep 29, 2026Фото 3 (с) Анатолий Кулаков
  3. Sep 29, 2026День 2799. Конференция DotNext 2026. Часть 1 25 и 26 сентября в Москве прошла очередная ко…
  4. Sep 28, 2026День 2798. #Оффтоп Утиная Типизация в C# с Помощью Перехватчиков. Часть 2 Некоторое время…
  5. Sep 27, 2026День 2797. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Окончание Начало Продол…
  6. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →