using GitConverter.Lib.Factories; using GitConverter.Lib.Converters; using GitConverter.TestsApp.TestSupport; namespace GitConverter.TestsApp.Factories { /// /// Lightweight unit tests verifying specific logging behaviors of . /// /// /// /// Purpose /// - Validate that emits diagnostic and error logs at the /// expected levels during construction, lookup misses, successful instantiation and failure /// to instantiate converter delegates. /// /// /// Test approach /// - Use a that captures emitted log messages. Assert on presence of /// tokens at the appropriate (Debug/Info/Warn/Error) rather than /// comparing complete strings to keep assertions resilient to wording changes. /// - Exercise both default built-in registrations (via the parameterless constructor) and /// custom registrations that simulate error conditions (factory delegate throwing). /// /// /// Important messages asserted in tests /// - Lookup miss: Debug message indicating a lookup miss when asking for an unknown key. /// - Suggestion warn: Warn-level message when Create() throws and suggests a close match. /// - Duplicate registration: Error-level message emitted when duplicate normalized keys are registered. /// - Instantiation success: Debug-level message emitted when a factory delegate returns a converter instance. /// - Instantiation failure: Warn-level message emitted when a factory delegate throws during TryCreate. /// - Registration summary: Info-level message emitted at factory initialization listing supported options. /// /// public class ConverterFactoryLoggingTests { [Fact] public void TryCreate_UnknownKey_LogsLookupMiss() { var logger = new TestLogger(); var factory = new ConverterFactory(null, logger); var ok = factory.TryCreate("this-does-not-exist", out var conv); Assert.False(ok); Assert.Null(conv); LogAssert.ContainsMessage(logger, LogLevel.Debug, "lookup miss"); } [Fact] public void Create_Typo_LogsSuggestionWarn() { var logger = new TestLogger(); var factory = new ConverterFactory(null, logger); var ex = Assert.Throws(() => factory.Create("esrijsn")); Assert.Contains("Did you mean", ex.Message, StringComparison.OrdinalIgnoreCase); LogAssert.ContainsMessage(logger, LogLevel.Warn, "suggest"); } [Fact] public void DuplicateRegistration_LogsError() { var registrations = new Dictionary>(StringComparer.Ordinal) { { "A", () => new UniversalGisConverter() }, { "a", () => new UniversalGisConverter() } // duplicates normalized key }; var logger = new TestLogger(); var ex = Record.Exception(() => new ConverterFactory(registrations, logger)); Assert.NotNull(ex); LogAssert.ContainsMessage(logger, LogLevel.Error, "duplicate registration"); } [Fact] public void TryCreate_Success_LogsInstantiation() { var logger = new TestLogger(); var factory = new ConverterFactory(null, logger); var ok = factory.TryCreate("GeoJson", out var conv); Assert.True(ok); Assert.NotNull(conv); // The factory logs a debug message indicating instantiation success LogAssert.ContainsMessage(logger, LogLevel.Debug, "instantiated converter"); } [Fact] public void Constructor_LogsRegistrationSummary_Info() { var logger = new TestLogger(); // Constructing the factory should log an info-level registration summary var factory = new ConverterFactory(null, logger); LogAssert.ContainsMessage(logger, LogLevel.Info, "initialized with options"); } [Fact] public void TryCreate_FactoryDelegateThrows_LogsWarn() { var registrations = new Dictionary>(StringComparer.OrdinalIgnoreCase) { { "Explode", () => throw new InvalidOperationException("boom") } }; var logger = new TestLogger(); var factory = new ConverterFactory(registrations, logger); var ok = factory.TryCreate("Explode", out var conv); Assert.False(ok); Assert.Null(conv); LogAssert.ContainsMessage(logger, LogLevel.Warn, "failed to instantiate converter"); } } }