Add test project and improve logging error handling#2
Conversation
olivegamestudio
commented
Dec 15, 2025
- Move main project to src/ and add tests/FluentLoggerExtensions.Tests
- Wrap CallerLogContextExtensions logging calls in try-catch to log errors on template/argument mismatch
- Add xUnit/Moq tests for all logging methods to verify robustness
- Add LoggerMoqExtensions helper for verifying log output in tests
- Move main project to src/ and add tests/FluentLoggerExtensions.Tests - Wrap CallerLogContextExtensions logging calls in try-catch to log errors on template/argument mismatch - Add xUnit/Moq tests for all logging methods to verify robustness - Add LoggerMoqExtensions helper for verifying log output in tests
There was a problem hiding this comment.
Pull request overview
This pull request restructures the project by moving the main library to a src/ directory and introduces a comprehensive test suite with error handling improvements. The primary goal is to improve the robustness of the logging extensions by wrapping logging calls in try-catch blocks to handle template/argument mismatches gracefully, while adding extensive tests to verify this behavior.
Key Changes:
- Added try-catch error handling to all logging methods (LogInformation, LogError, LogDebug, LogWarning) to prevent exceptions from template/argument mismatches
- Created a new test project with xUnit/Moq tests covering all logging scenarios including edge cases
- Reorganized project structure by moving source code to
src/directory
Reviewed changes
Copilot reviewed 10 out of 12 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
tests/FluentLoggerExtensions.Tests/FluentLoggerExtensions.Tests.csproj |
New test project configuration with xUnit, Moq, and test SDK dependencies |
tests/FluentLoggerExtensions.Tests/LoggerMoqExtensions.cs |
Helper extension for verifying log output in tests using Moq |
tests/FluentLoggerExtensions.Tests/CallerLogContextLogInformationTests.cs |
Test suite for LogInformation method covering various scenarios |
tests/FluentLoggerExtensions.Tests/CallerLogContextLogWarningTests.cs |
Test suite for LogWarning method covering various scenarios |
tests/FluentLoggerExtensions.Tests/CallerLogContextLogErrorTests.cs |
Test suite for LogError method covering various scenarios |
tests/FluentLoggerExtensions.Tests/CallerLogContextLogDebugTests.cs |
Test suite for LogDebug method covering various scenarios |
src/CallerLogContextExtensions.cs |
Added try-catch error handling to all logging methods with fallback error logging |
src/FluentLoggerExtensions.cs |
New file containing the WithCaller extension method (moved from original location) |
src/CallerLogContext.cs |
New file defining the CallerLogContext struct (moved from original location) |
src/FluentLoggerExtensions.csproj |
Updated project file to include README in NuGet package |
FluentLoggerExtensions.slnx |
Updated solution file to reference reorganized projects |
.github/workflows/dotnet-desktop.yml |
Added test execution step and automated version tagging |
Comments suppressed due to low confidence (5)
src/CallerLogContextExtensions.cs:18
- The variable 'fileName' is declared as non-nullable (string), but context.File is nullable (string?). If context.File is null, Path.GetFileName will return an empty string, which is then assigned to a non-nullable variable. Consider either declaring fileName as string? or using the null-forgiving operator (!) if null is not expected.
src/CallerLogContextExtensions.cs:44 - The variable 'fileName' is declared as non-nullable (string), but context.File is nullable (string?). If context.File is null, Path.GetFileName will return an empty string, which is then assigned to a non-nullable variable. Consider either declaring fileName as string? or using the null-forgiving operator (!) if null is not expected.
src/CallerLogContextExtensions.cs:70 - The variable 'fileName' is declared as non-nullable (string), but context.File is nullable (string?). If context.File is null, Path.GetFileName will return an empty string, which is then assigned to a non-nullable variable. Consider either declaring fileName as string? or using the null-forgiving operator (!) if null is not expected.
src/CallerLogContextExtensions.cs:96 - The variable 'fileName' is declared as non-nullable (string), but context.File is nullable (string?). If context.File is null, Path.GetFileName will return an empty string, which is then assigned to a non-nullable variable. Consider either declaring fileName as string? or using the null-forgiving operator (!) if null is not expected.
src/CallerLogContextExtensions.cs:84 - Using LogDebug in the error handler for a failed LogDebug call is problematic. If the logger is misconfigured or has issues, this could silently swallow the error since debug logs are often disabled in production. Consider using LogError or LogWarning for the fallback logging to ensure the failure is visible.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ), | ||
| It.IsAny<Exception>(), | ||
| It.IsAny<Func<It.IsAnyType, Exception?, string>>()), | ||
| Times.Once); |
There was a problem hiding this comment.
The 'times' parameter is declared but never used in the method. It should either be removed if not needed, or passed to the Verify call. Currently, the verification always uses Times.Once regardless of the 'times' parameter value.
| Times.Once); | |
| times ?? Times.Once); |
| [Theory] | ||
| [InlineData("This is a test log message")] | ||
| [InlineData("This is another test log message")] | ||
| [InlineData("This is a really log test message")] |
There was a problem hiding this comment.
The test description "This is a really log test message" contains a grammatical error. It should be "This is a really long test message" (with "long" instead of "log").
| [InlineData("This is a really log test message")] | |
| [InlineData("This is a really long test message")] |
| } | ||
|
|
||
| [Fact] | ||
| public void Mismatched_placeholders_throw_when_state_is_enumerated() |
There was a problem hiding this comment.
The test method name uses snake_case naming convention ("Mismatched_placeholders_throw_when_state_is_enumerated"), which is inconsistent with the PascalCase naming used in other test methods in this file (e.g., "LogWarning_WithPlainMessage_DoesNotThrow"). Consider renaming to "MismatchedPlaceholders_ThrowWhenStateIsEnumerated" for consistency.
| public void Mismatched_placeholders_throw_when_state_is_enumerated() | |
| public void MismatchedPlaceholders_ThrowWhenStateIsEnumerated() |
| [Theory] | ||
| [InlineData("This is a test log message")] | ||
| [InlineData("This is another test log message")] | ||
| [InlineData("This is a really log test message")] |
There was a problem hiding this comment.
The test description "This is a really log test message" contains a grammatical error. It should be "This is a really long test message" (with "long" instead of "log").
| [InlineData("This is a really log test message")] | |
| [InlineData("This is a really long test message")] |
| } | ||
|
|
||
| [Fact] | ||
| public void Mismatched_placeholders_throw_when_state_is_enumerated() |
There was a problem hiding this comment.
The test method name uses snake_case naming convention ("Mismatched_placeholders_throw_when_state_is_enumerated"), which is inconsistent with the PascalCase naming used in other test methods in this file (e.g., "LogInformation_WithPlainMessage_DoesNotThrow"). Consider renaming to "MismatchedPlaceholders_ThrowWhenStateIsEnumerated" for consistency.
| public void Mismatched_placeholders_throw_when_state_is_enumerated() | |
| public void MismatchedPlaceholders_ThrowWhenStateIsEnumerated() |
| [Theory] | ||
| [InlineData("This is a test log message")] | ||
| [InlineData("This is another test log message")] | ||
| [InlineData("This is a really log test message")] |
There was a problem hiding this comment.
The test description "This is a really log test message" contains a grammatical error. It should be "This is a really long test message" (with "long" instead of "log").
| [InlineData("This is a really log test message")] | |
| [InlineData("This is a really long test message")] |
| } | ||
|
|
||
| [Fact] | ||
| public void Mismatched_placeholders_throw_when_state_is_enumerated() |
There was a problem hiding this comment.
The test method name uses snake_case naming convention ("Mismatched_placeholders_throw_when_state_is_enumerated"), which is inconsistent with the PascalCase naming used in other test methods in this file (e.g., "LogError_WithPlainMessage_DoesNotThrow"). Consider renaming to "MismatchedPlaceholders_ThrowWhenStateIsEnumerated" for consistency.
| public void Mismatched_placeholders_throw_when_state_is_enumerated() | |
| public void MismatchedPlaceholders_ThrowWhenStateIsEnumerated() |
| } | ||
|
|
||
| [Fact] | ||
| public void Mismatched_placeholders_throw_when_state_is_enumerated() |
There was a problem hiding this comment.
The test method name uses snake_case naming convention ("Mismatched_placeholders_throw_when_state_is_enumerated"), which is inconsistent with the PascalCase naming used in other test methods in this file (e.g., "LogDebug_WithPlainMessage_DoesNotThrow"). Consider renaming to "MismatchedPlaceholders_ThrowWhenStateIsEnumerated" for consistency.
| public void Mismatched_placeholders_throw_when_state_is_enumerated() | |
| public void MismatchedPlaceholders_ThrowWhenStateIsEnumerated() |
| [Theory] | ||
| [InlineData("This is a test log message")] | ||
| [InlineData("This is another test log message")] | ||
| [InlineData("This is a really log test message")] |
There was a problem hiding this comment.
The test description "This is a really log test message" contains a grammatical error. It should be "This is a really long test message" (with "long" instead of "log").
| [InlineData("This is a really log test message")] | |
| [InlineData("This is a really long test message")] |