FaultGenerator's implicit conversion dereferenced the nullable Outcome
returned by the underlying generator via `!.Value`, throwing
InvalidOperationException ("Nullable object must have a value.") when the
generator produced no outcome - an empty generator, or registered weights
summing to zero. ChaosFaultStrategy treats a null fault as "do not inject"
and only catches OperationCanceledException, so the exception escaped and
failed the execution the strategy was meant to leave untouched.
Propagate the nullable outcome with `?.Exception`, mirroring
OutcomeGenerator<TResult>, so no fault is injected when none is generated.
69 lines
1.7 KiB
C#
69 lines
1.7 KiB
C#
using Polly.Simmy.Fault;
|
|
|
|
namespace Polly.Core.Tests.Simmy.Fault;
|
|
|
|
public class FaultGeneratorTests
|
|
{
|
|
[Fact]
|
|
public void AddException_Generic_Ok()
|
|
{
|
|
var generator = new FaultGenerator();
|
|
|
|
generator.AddException<InvalidOperationException>();
|
|
|
|
Generate(generator).ShouldBeOfType<InvalidOperationException>();
|
|
}
|
|
|
|
[Fact]
|
|
public void AddException_Factory_Ok()
|
|
{
|
|
var generator = new FaultGenerator();
|
|
|
|
generator.AddException(() => new InvalidOperationException());
|
|
|
|
Generate(generator).ShouldBeOfType<InvalidOperationException>();
|
|
}
|
|
|
|
[Fact]
|
|
public void AddException_FactoryWithResilienceContext_Ok()
|
|
{
|
|
var generator = new FaultGenerator();
|
|
|
|
generator.AddException(context =>
|
|
{
|
|
context.ShouldNotBeNull();
|
|
|
|
return new InvalidOperationException();
|
|
});
|
|
|
|
Generate(generator).ShouldBeOfType<InvalidOperationException>();
|
|
}
|
|
|
|
[Fact]
|
|
public void NoExceptionRegistered_ShouldReturnNull()
|
|
{
|
|
var generator = new FaultGenerator();
|
|
|
|
Generate(generator).ShouldBeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void AllWeightsZero_ShouldReturnNull()
|
|
{
|
|
var generator = new FaultGenerator();
|
|
|
|
generator.AddException<InvalidOperationException>(weight: 0);
|
|
|
|
Generate(generator).ShouldBeNull();
|
|
}
|
|
|
|
private static Exception? Generate(FaultGenerator generator)
|
|
{
|
|
Func<FaultGeneratorArguments, ValueTask<Exception?>> func = generator;
|
|
|
|
return func(
|
|
new FaultGeneratorArguments(
|
|
ResilienceContextPool.Shared.Get(TestCancellation.Token))).AsTask().Result;
|
|
}
|
|
}
|