`dotnet test test/unit/Elsa.Resilience.Core.UnitTests` exited 1 on a clean checkout with all 56 tests passing. The failure was the coverlet gate, not a test: the project pinned `<Threshold>49</Threshold>` against 48.17% measured line coverage in Debug. Release measures slightly differently and cleared it, so CI (which builds `--configuration Release`) stayed green while every local run — Debug is the default — went red. A red exit for a suite that passes trains people to ignore exit codes. Rather than move the goalposts, cover the code. The gap was concentrated in `ResilientActivityInvoker`, which had no tests at all, plus the serializer, the activity-execution extensions and the retry telemetry listener. `Elsa.Testing.Shared`'s `ActivityTestFixture` was already referenced here and builds a real `ActivityExecutionContext`, which is what all of them needed. Adds 40 tests. The invoker ones drive a real zero-delay Polly retry pipeline, so the telemetry listener is exercised through the actual Polly path rather than being called directly: pass-through when no strategy is configured, the applied strategy recorded on the context, retry-then-succeed, one record per retry carrying identifiers and details, null details dropped, the retries flag and attempt count, exhausted retries rethrowing, and an unhandled exception type not being retried. The extensions tests build a three-level context chain to pin down that the retries flag propagates up the ancestor chain and not down. Line coverage goes 48.17% -> 98.17% in Debug and 97.8% in Release; the five lines still uncovered are defensive early-returns. The threshold moves to 90, below the lower of the two configurations with enough headroom that the Debug/Release delta cannot straddle it again. Verified by deleting the invoker tests once: coverage falls to 68.97% and the gate fails as it should. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
48 lines
1.8 KiB
C#
48 lines
1.8 KiB
C#
using Elsa.Resilience.Core.UnitTests.TestHelpers;
|
|
using Elsa.Resilience.Extensions;
|
|
using Elsa.Resilience.Options;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
namespace Elsa.Resilience.Core.UnitTests;
|
|
|
|
public class ResilienceServiceCollectionExtensionsTests
|
|
{
|
|
private readonly IServiceCollection _services = new ServiceCollection();
|
|
|
|
private ResilienceOptions GetOptions() => _services.BuildServiceProvider().GetRequiredService<IOptions<ResilienceOptions>>().Value;
|
|
|
|
[Fact(DisplayName = "AddResilienceStrategy should register the strategy type")]
|
|
public void AddResilienceStrategy_RegistersType()
|
|
{
|
|
_services.AddResilienceStrategy<TestRetryStrategy>();
|
|
|
|
Assert.Equal([typeof(TestRetryStrategy)], GetOptions().StrategyTypes);
|
|
}
|
|
|
|
[Fact(DisplayName = "AddResilienceStrategy should accumulate across calls")]
|
|
public void AddResilienceStrategy_CalledTwice_RegistersBothTypes()
|
|
{
|
|
_services.AddResilienceStrategy<TestRetryStrategy>();
|
|
_services.AddResilienceStrategy<TestNoopStrategy>();
|
|
|
|
Assert.Equal([typeof(TestRetryStrategy), typeof(TestNoopStrategy)], GetOptions().StrategyTypes);
|
|
}
|
|
|
|
[Fact(DisplayName = "AddResilienceStrategies should register every supplied type")]
|
|
public void AddResilienceStrategies_RegistersAllTypes()
|
|
{
|
|
_services.AddResilienceStrategies([typeof(TestRetryStrategy), typeof(TestNoopStrategy)]);
|
|
|
|
Assert.Equal([typeof(TestRetryStrategy), typeof(TestNoopStrategy)], GetOptions().StrategyTypes);
|
|
}
|
|
|
|
[Fact(DisplayName = "AddResilienceStrategies with an empty sequence should leave options untouched")]
|
|
public void AddResilienceStrategies_EmptySequence_RegistersNothing()
|
|
{
|
|
_services.AddResilienceStrategies([]);
|
|
|
|
Assert.Empty(GetOptions().StrategyTypes);
|
|
}
|
|
}
|