-
Notifications
You must be signed in to change notification settings - Fork 5
Expand messaging extension test coverage #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds new unit tests across NATS, RabbitMQ, and AWS SQS-related components: a NATS heartbeat override test, a RabbitMQ connectivity thread-safety test, SQS visibility timeout clamping test, SQS client config extension tests, and SNS URI string extension tests. No production code changes. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant T as Test
participant R as RabbitMqMessage
participant F as IConnectionFactory (mock)
participant C as IConnection (mock)
participant CH as IChannel (mock)
Note over T,R: Concurrent initialization
T->>R: EnsureConnectivityAsync()
par Concurrent call
T->>R: EnsureConnectivityAsync()
and
T->>R: EnsureConnectivityAsync()
end
alt First initialization path
R->>F: CreateConnectionAsync()
F-->>R: C
R->>C: CreateChannelAsync()
C-->>R: CH
R-->>T: Completed
else Already initialized
R-->>T: Completed (no new connection)
end
Note over F: Verify called exactly once
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Pre-merge checks (2 passed, 1 warning)❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Poem
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).Please share your feedback with us on this Discord post. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (3)
test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageReceiveOptionsTest.cs (1)
49-59: Good clamp coverage; add boundary asserts inline.Nice edge coverage. Add explicit boundary checks for 0s and exactly Max to prevent regressions.
Apply this diff:
[Fact] public void VisibilityTimeout_ShouldClampValue_WhenOutsideRangeOfAllowedLimits() { var sut = new AmazonMessageReceiveOptions(); sut.VisibilityTimeout = TimeSpan.MinValue; Assert.Equal(TimeSpan.Zero, sut.VisibilityTimeout); + + // Lower boundary exact + sut.VisibilityTimeout = TimeSpan.Zero; + Assert.Equal(TimeSpan.Zero, sut.VisibilityTimeout); sut.VisibilityTimeout = TimeSpan.FromSeconds(AmazonMessageOptions.MaxVisibilityTimeoutInSeconds + 1); Assert.Equal(TimeSpan.FromSeconds(AmazonMessageOptions.MaxVisibilityTimeoutInSeconds), sut.VisibilityTimeout); + + // Upper boundary exact + sut.VisibilityTimeout = TimeSpan.FromSeconds(AmazonMessageOptions.MaxVisibilityTimeoutInSeconds); + Assert.Equal(TimeSpan.FromSeconds(AmazonMessageOptions.MaxVisibilityTimeoutInSeconds), sut.VisibilityTimeout); }test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cs (1)
72-82: Override behavior looks correct; strengthen with persistence check.After manual override, ensure subsequent Expires updates don’t reset Heartbeat.
Apply this diff:
public void Heartbeat_Can_Be_Overridden_After_Expires() { var options = new NatsCommandQueueOptions(); options.Expires = TimeSpan.FromSeconds(60); Assert.Equal(TimeSpan.FromSeconds(5), options.Heartbeat); options.Heartbeat = TimeSpan.FromSeconds(15); Assert.Equal(TimeSpan.FromSeconds(15), options.Heartbeat); + + // Verify override persists even if Expires changes again + options.Expires = TimeSpan.FromSeconds(45); + Assert.Equal(TimeSpan.FromSeconds(15), options.Heartbeat); }test/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cs (1)
14-25: Solid validity checks.Covers null, happy path, and wrong length. Consider adding a case with unrelated configs to assert false.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
test/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cs(1 hunks)test/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageTest.cs(1 hunks)test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageReceiveOptionsTest.cs(1 hunks)test/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cs(1 hunks)test/Savvyio.Extensions.SimpleQueueService.Tests/EventDriven/StringExtensionsTest.cs(1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*Test.cs
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*Test.cs: All unit test classes must inherit from Codebelt.Extensions.Xunit.Test
Use [Fact] for standard unit tests
Use [Theory] with [InlineData] or other data sources for parameterized tests
Test method names should be descriptive and express expected behavior (e.g., ShouldReturnTrue_WhenConditionIsMet)
Use xUnit Assert methods for all assertions (e.g., Assert.Equal, Assert.NotNull, Assert.Contains)
Keep tests focused, isolated, deterministic, and repeatable; avoid external systems except xUnit and Codebelt.Extensions.Xunit
Prefer dummies, fakes, stubs, and spies; use Moq-based mocks only when necessary
Before overriding or mocking, ensure targeted methods are virtual or abstract
Never mock IMarshaller; use a new JsonMarshaller instance instead
Files:
test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageReceiveOptionsTest.cstest/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cstest/Savvyio.Extensions.SimpleQueueService.Tests/EventDriven/StringExtensionsTest.cstest/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cstest/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageTest.cs
test/**/*Test.cs
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Test class files must be named with a Test suffix (e.g., CommandDispatcherTest)
Files:
test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageReceiveOptionsTest.cstest/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cstest/Savvyio.Extensions.SimpleQueueService.Tests/EventDriven/StringExtensionsTest.cstest/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cstest/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageTest.cs
test/**
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Place tests in dedicated test projects/folders (under the test directory)
Files:
test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageReceiveOptionsTest.cstest/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cstest/Savvyio.Extensions.SimpleQueueService.Tests/EventDriven/StringExtensionsTest.cstest/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cstest/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageTest.cs
test/**/*.cs
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use namespaces in tests that mirror the source code structure
Files:
test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageReceiveOptionsTest.cstest/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cstest/Savvyio.Extensions.SimpleQueueService.Tests/EventDriven/StringExtensionsTest.cstest/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cstest/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageTest.cs
test/**/*.Tests/**
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Unit tests for an assembly should reside in a corresponding .Tests assembly (e.g., Savvyio.Foo.Tests)
Files:
test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageReceiveOptionsTest.cstest/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cstest/Savvyio.Extensions.SimpleQueueService.Tests/EventDriven/StringExtensionsTest.cstest/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cstest/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageTest.cs
**/*.cs
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.cs: Follow the repository’s established XML documentation style
Add XML documentation comments to public and protected classes and methods where appropriate
Files:
test/Savvyio.Extensions.SimpleQueueService.Tests/AmazonMessageReceiveOptionsTest.cstest/Savvyio.Extensions.NATS.Tests/Commands/NatsCommandQueueOptionsTest.cstest/Savvyio.Extensions.SimpleQueueService.Tests/EventDriven/StringExtensionsTest.cstest/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cstest/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageTest.cs
🧬 Code graph analysis (1)
test/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageTest.cs (1)
src/Savvyio.Extensions.RabbitMQ/RabbitMqMessage.cs (4)
Task(67-84)Task(118-121)RabbitMqMessage(14-122)RabbitMqMessage(36-45)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: call-build (Release) / 🛠️ Build
🔇 Additional comments (3)
test/Savvyio.Extensions.SimpleQueueService.Tests/EventDriven/StringExtensionsTest.cs (2)
20-31: LGTM.Custom options path is clear and assertions are precise.
12-18: Defaults test verified — implementation defaults match the asserted ARN. ToSnsUri builds arn:{options.Partition}:sns:{options.Region}:{options.AccountId}:{source} (src/Savvyio.Extensions.SimpleQueueService/EventDriven/StringExtensions.cs) and AmazonResourceNameOptions defaults are Partition = RegionEndpoint.EUWest1.PartitionName, Region = RegionEndpoint.EUWest1.SystemName, AccountId = "000000000000" (src/Savvyio.Extensions.SimpleQueueService/AmazonResourceNameOptions.cs).test/Savvyio.Extensions.SimpleQueueService.Tests/ClientConfigExtensionsTest.cs (1)
27-36: LGTM.Resolution helpers correctly return the expected instances.
| [Fact] | ||
| public async Task EnsureConnectivityAsync_IsThreadSafe_WhenCalledConcurrently() | ||
| { | ||
| var marshaller = new Mock<IMarshaller>().Object; | ||
| var options = new RabbitMqMessageOptions { AmqpUrl = new Uri("amqp://localhost:5672") }; | ||
|
|
||
| var connectionMock = new Mock<IConnection>(); | ||
| var channelMock = new Mock<IChannel>(); | ||
| connectionMock.Setup(c => c.CreateChannelAsync(It.IsAny<CreateChannelOptions?>(), It.IsAny<CancellationToken>())) | ||
| .ReturnsAsync(channelMock.Object); | ||
|
|
||
| var factoryMock = new Mock<IConnectionFactory>(); | ||
| factoryMock.Setup(f => f.CreateConnectionAsync(It.IsAny<CancellationToken>())) | ||
| .ReturnsAsync(connectionMock.Object); | ||
|
|
||
| var sut = new TestRabbitMqMessage(marshaller, options); | ||
| typeof(RabbitMqMessage) | ||
| .GetProperty("RabbitMqFactory", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) | ||
| .SetValue(sut, factoryMock.Object); | ||
|
|
||
| await Task.WhenAll( | ||
| sut.CallEnsureConnectivityAsync(), | ||
| sut.CallEnsureConnectivityAsync()); | ||
|
|
||
| factoryMock.Verify(f => f.CreateConnectionAsync(It.IsAny<CancellationToken>()), Times.Once); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Don’t mock IMarshaller; use a JsonMarshaller. Also verify CreateChannelAsync once.
Repo guideline: “Never mock IMarshaller; use a new JsonMarshaller instance instead.” Replace the mock and add a verify for channel creation.
Apply this diff:
public async Task EnsureConnectivityAsync_IsThreadSafe_WhenCalledConcurrently()
{
- var marshaller = new Mock<IMarshaller>().Object;
+ var marshaller = new JsonMarshaller();
var options = new RabbitMqMessageOptions { AmqpUrl = new Uri("amqp://localhost:5672") };
@@
await Task.WhenAll(
sut.CallEnsureConnectivityAsync(),
sut.CallEnsureConnectivityAsync());
factoryMock.Verify(f => f.CreateConnectionAsync(It.IsAny<CancellationToken>()), Times.Once);
+ connectionMock.Verify(c => c.CreateChannelAsync(It.IsAny<CreateChannelOptions?>(), It.IsAny<CancellationToken>()), Times.Once);
}Add the appropriate using for JsonMarshaller (adjust namespace to your concrete type if different):
using Savvyio.Serialization; // or the namespace where JsonMarshaller resides🤖 Prompt for AI Agents
In test/Savvyio.Extensions.RabbitMQ.Tests/RabbitMqMessageTest.cs around lines
104 to 129, replace the mocked IMarshaller with a real JsonMarshaller instance
(add the appropriate using for its namespace), and after the concurrent
EnsureConnectivity calls add a Verify on the connectionMock.CreateChannelAsync
(or channelMock depending on method) to assert it was invoked once;
specifically: construct new JsonMarshaller() instead of
Mock<IMarshaller>().Object, add the using for Savvyio.Serialization (or the
correct namespace), and add factoryMock.Verify for
CreateConnectionAsync(Times.Once) is already present and add
channelMock.Verify(c => c.CreateChannelAsync(It.IsAny<CreateChannelOptions?>(),
It.IsAny<CancellationToken>()), Times.Once) to confirm single channel creation.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #41 +/- ##
==========================================
+ Coverage 77.82% 78.01% +0.18%
==========================================
Files 177 177
Lines 3711 3711
Branches 365 365
==========================================
+ Hits 2888 2895 +7
+ Misses 821 815 -6
+ Partials 2 1 -1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|



Summary
Testing
for proj in $(find test -name '*.csproj' | grep -v FunctionalTests); do dotnet test $proj; donehttps://chatgpt.com/codex/tasks/task_e_68c1e1e6cc5c83308a173cdc61ea3b36
Summary by CodeRabbit