From 83504d92f28e4c3a7158fde793c39dc3b90a2b1a Mon Sep 17 00:00:00 2001 From: Robert Bennett Date: Tue, 13 Jun 2023 12:53:19 +0100 Subject: [PATCH] Stop subsequent ExecuteAsync calls from executing previously executed steps. Add rewind method to allow ExecuteAsync to execute previously executed steps. --- .../Abstractions/IFluentHttpClient.cs | 7 ++ src/Fluent.Http/FluentHttpClient.cs | 30 +++++--- .../FluentHttpClientTests.cs | 72 +++++++++++++++++++ 3 files changed, 101 insertions(+), 8 deletions(-) diff --git a/src/Fluent.Http/Abstractions/IFluentHttpClient.cs b/src/Fluent.Http/Abstractions/IFluentHttpClient.cs index 50624f9..92a957d 100644 --- a/src/Fluent.Http/Abstractions/IFluentHttpClient.cs +++ b/src/Fluent.Http/Abstractions/IFluentHttpClient.cs @@ -53,5 +53,12 @@ IFluentHttpClient Step( /// Executes all the steps defined in the /// Task ExecuteAsync(); + + /// + /// Rewinds the number of steps provided or all of them if null is passed. This allows multiple calls to execute async to run the same steps. + /// + /// The number of steps to rewind. All of them if null is provided. + /// + IFluentHttpClient Rewind(Int32? count = null); } } \ No newline at end of file diff --git a/src/Fluent.Http/FluentHttpClient.cs b/src/Fluent.Http/FluentHttpClient.cs index 5d17f45..489f53a 100644 --- a/src/Fluent.Http/FluentHttpClient.cs +++ b/src/Fluent.Http/FluentHttpClient.cs @@ -3,6 +3,7 @@ using Fluent.Http.Exceptions; using System; using System.Collections.Generic; +using System.Linq; using System.Net.Http; using System.Threading.Tasks; @@ -12,6 +13,7 @@ namespace Fluent.Http public class FluentHttpClient : IFluentHttpClient { private readonly HttpClient _client; + private Int32 _numberOfStepsExectued = 0; private FluentHttpClient(HttpClient? client) => _client = client ?? new HttpClient(); @@ -65,11 +67,10 @@ public IFluentHttpClient Step( /// public async Task ExecuteAsync() { - Int32 counter = 1; - - foreach (IFluentStep step in Steps) + foreach (IFluentStep step in Steps.Skip(_numberOfStepsExectued)) { - step.SequenceNumber = counter; + Int32 stepSequenceNumber = _numberOfStepsExectued + 1; + step.SequenceNumber = stepSequenceNumber; try { @@ -77,7 +78,7 @@ public async Task ExecuteAsync() } catch (Exception e) { - throw new FluentStepFailedException(counter, step.Name, e); + throw new FluentStepFailedException(stepSequenceNumber, step.Name, e); } if (step is IFluentValidationStep validationStep) @@ -88,13 +89,26 @@ public async Task ExecuteAsync() } catch (Exception e) { - throw new FluentStepValidationFailedException(counter, step.Name, e); + throw new FluentStepValidationFailedException(stepSequenceNumber, step.Name, e); } } - - counter++; + + _numberOfStepsExectued++; } } + /// + public IFluentHttpClient Rewind(Int32? count = null) + { + count ??= _numberOfStepsExectued; + _numberOfStepsExectued -= count.Value; + + if (_numberOfStepsExectued < 0) + { + _numberOfStepsExectued = 0; + } + + return this; + } } } \ No newline at end of file diff --git a/tests/Fluent.Http.Tests/FluentHttpClientTests.cs b/tests/Fluent.Http.Tests/FluentHttpClientTests.cs index 0b25410..d03b429 100644 --- a/tests/Fluent.Http.Tests/FluentHttpClientTests.cs +++ b/tests/Fluent.Http.Tests/FluentHttpClientTests.cs @@ -114,5 +114,77 @@ await client.Step( calledStep.Should().BeTrue(); calledPostStep.Should().BeTrue(); } + + [Fact] + public async Task ExecuteAsync_MultipleCalls_DoesNotExecuteStepsTwice() + { + _handler + .When(HttpMethod.Get, "http://test.com/api/test") + .Respond(HttpStatusCode.OK); + + int stepOneCallCount = 0; + int stepTwoCallCount = 0; + + IFluentHttpClient client = FluentHttpClient.Build(_client); + + await client.Step( + () => + { + stepOneCallCount++; + return Task.CompletedTask; + }) + .ExecuteAsync(); + + await client.Step( + () => + { + stepTwoCallCount++; + return Task.CompletedTask; + }) + .ExecuteAsync(); + + stepOneCallCount.Should().Be(1); + stepTwoCallCount.Should().Be(1); + } + + [Fact] + public async Task ExecuteAsync_WithRewind_AllowsMultipleCalls() + { + _handler + .When(HttpMethod.Get, "http://test.com/api/test") + .Respond(HttpStatusCode.OK); + + int stepOneCallCount = 0; + int stepTwoCallCount = 0; + + IFluentHttpClient client = FluentHttpClient.Build(_client); + + await client.Step( + () => + { + stepOneCallCount++; + return Task.CompletedTask; + }) + .ExecuteAsync(); + + await client.Step( + () => + { + stepTwoCallCount++; + return Task.CompletedTask; + }) + .ExecuteAsync(); + + await client + .Rewind(1) + .ExecuteAsync(); + + await client + .Rewind() + .ExecuteAsync(); + + stepOneCallCount.Should().Be(2); + stepTwoCallCount.Should().Be(3); + } } } \ No newline at end of file