Add project files.
This commit is contained in:
+15
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\common\Elsa.Testing.Shared.Integration\Elsa.Testing.Shared.Integration.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\common\Elsa.Testing.Shared\Elsa.Testing.Shared.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.Http\Elsa.Http.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.Resilience\Elsa.Resilience.csproj" />
|
||||
<ProjectReference Include="..\..\..\src\modules\Elsa.Workflows.Core\Elsa.Workflows.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
using System.Net;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Http;
|
||||
using Elsa.Resilience.Extensions;
|
||||
using Elsa.Resilience.Models;
|
||||
using Elsa.Testing.Shared;
|
||||
using Elsa.Workflows;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Elsa.Resilience.IntegrationTests;
|
||||
|
||||
public class FlowSendHttpRequestResilienceTests
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly TestRetryAttemptRecorder _recorder = new();
|
||||
|
||||
public FlowSendHttpRequestResilienceTests(ITestOutputHelper output)
|
||||
{
|
||||
var handler = new SequentialStatusHandler([HttpStatusCode.TooManyRequests, HttpStatusCode.ServiceUnavailable, HttpStatusCode.OK]);
|
||||
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["Resilience:Strategies:0:$type"] = "HttpResilienceStrategy",
|
||||
["Resilience:Strategies:0:Id"] = "test",
|
||||
["Resilience:Strategies:0:DisplayName"] = "Test",
|
||||
["Resilience:Strategies:0:MaxRetryAttempts"] = "5",
|
||||
["Resilience:Strategies:0:Delay"] = "00:00:00.001"
|
||||
})
|
||||
.Build();
|
||||
|
||||
_services = new TestApplicationBuilder(output)
|
||||
.ConfigureServices(s =>
|
||||
{
|
||||
s.AddSingleton<IConfiguration>(configuration);
|
||||
})
|
||||
.ConfigureElsa(module =>
|
||||
{
|
||||
module.UseHttp(http =>
|
||||
{
|
||||
http.HttpClientBuilder = builder => builder.ConfigurePrimaryHttpMessageHandler(() => handler);
|
||||
});
|
||||
|
||||
module.UseResilience(resilience =>
|
||||
{
|
||||
resilience.WithRetryAttemptRecorder(_ => _recorder);
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "FlowSendHttpRequest retries using selected resilience strategy")]
|
||||
public async Task InvokesResilienceStrategy()
|
||||
{
|
||||
var activity = new FlowSendHttpRequest
|
||||
{
|
||||
Url = new(new Uri("http://localhost/test")),
|
||||
Method = new("GET"),
|
||||
ExpectedStatusCodes = new([200]),
|
||||
CustomProperties =
|
||||
{
|
||||
["resilienceStrategy"] = new ResilienceStrategyConfig
|
||||
{
|
||||
Mode = ResilienceStrategyConfigMode.Identifier,
|
||||
StrategyId = "test"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var result = await _services.RunActivityAsync(activity);
|
||||
var statusCode = result.GetActivityOutput<int>(activity, nameof(SendHttpRequestBase.StatusCode));
|
||||
|
||||
Assert.Equal(200, statusCode);
|
||||
Assert.Equal(2, _recorder.Attempts.Count);
|
||||
Assert.Collection(_recorder.Attempts,
|
||||
first => Assert.Equal(0, first.AttemptNumber),
|
||||
second => Assert.Equal(1, second.AttemptNumber));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
namespace Elsa.Resilience.IntegrationTests;
|
||||
|
||||
public class SequentialStatusHandler(IEnumerable<HttpStatusCode> codes) : HttpMessageHandler
|
||||
{
|
||||
private readonly Queue<HttpStatusCode> _codes = new(codes);
|
||||
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
var code = _codes.Count > 0 ? _codes.Dequeue() : _codes.Last();
|
||||
var response = new HttpResponseMessage(code)
|
||||
{
|
||||
Content = new StringContent(string.Empty)
|
||||
};
|
||||
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
|
||||
return Task.FromResult(response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Elsa.Resilience.Entities;
|
||||
using Elsa.Resilience.Models;
|
||||
|
||||
namespace Elsa.Resilience.IntegrationTests;
|
||||
|
||||
public class TestRetryAttemptRecorder : IRetryAttemptRecorder
|
||||
{
|
||||
public IList<RetryAttemptRecord> Attempts { get; } = new List<RetryAttemptRecord>();
|
||||
|
||||
public Task RecordAsync(RecordRetryAttemptsContext context)
|
||||
{
|
||||
foreach (var record in context.Attempts)
|
||||
Attempts.Add(record);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
global using Xunit;
|
||||
Reference in New Issue
Block a user