Skip to content

Commit

Permalink
tmenier#673 HttpTest Response based on request
Browse files Browse the repository at this point in the history
Allow HttpTest.RespondWith to access the request when constructing the response.
  • Loading branch information
kkd83 committed Feb 15, 2022
1 parent 9b9b2a6 commit eb0c043
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 8 deletions.
17 changes: 17 additions & 0 deletions Test/Flurl.Test/Http/TestingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Net.Http;
using System.Threading.Tasks;
using Flurl.Http;
using Flurl.Http.Content;
using Flurl.Http.Testing;
using NUnit.Framework;

Expand Down Expand Up @@ -499,5 +500,21 @@ public async Task can_use_response_queue_in_parallel() {
}
}
}

[Test] // #673
public async Task can_use_request_in_response()
{
HttpTest.RespondWith(request =>
{
var requestBody = request.Content.ReadAsStringAsync().GetAwaiter().GetResult();
return new CapturedStringContent(requestBody);
});

var receivedString = await "http://api.com"
.PostStringAsync("hello world")
.ReceiveString();

Assert.AreEqual("hello world", receivedString);
}
}
}
2 changes: 1 addition & 1 deletion src/Flurl.Http/Testing/FakeHttpMessageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage reques
HttpTest.Current.LogCall(call);
var setup = HttpTest.Current.FindSetup(call);
if (setup?.FakeRequest == true) {
var resp = setup.GetNextResponse() ?? new HttpResponseMessage {
var resp = setup.GetNextResponse(request) ?? new HttpResponseMessage {
StatusCode = HttpStatusCode.OK,
Content = new StringContent("")
};
Expand Down
37 changes: 30 additions & 7 deletions src/Flurl.Http/Testing/HttpTestSetup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace Flurl.Http.Testing
/// </summary>
public abstract class HttpTestSetup
{
private readonly List<Func<HttpResponseMessage>> _responses = new List<Func<HttpResponseMessage>>();
private readonly List<Func<HttpRequestMessage, HttpResponseMessage>> _responses = new List<Func<HttpRequestMessage, HttpResponseMessage>>();

private int _respIndex = 0;
private bool _allowRealHttp = false;
Expand All @@ -35,12 +35,12 @@ protected HttpTestSetup(TestFlurlHttpSettings settings) {

internal bool FakeRequest => !_allowRealHttp;

internal HttpResponseMessage GetNextResponse() {
internal HttpResponseMessage GetNextResponse(HttpRequestMessage request) {
if (!_responses.Any())
return null;

// atomically get the next response in the list, or the last one if we're past the end
return _responses[Math.Min(Interlocked.Increment(ref _respIndex), _responses.Count) - 1]();
return _responses[Math.Min(Interlocked.Increment(ref _respIndex), _responses.Count) - 1](request);
}

/// <summary>
Expand Down Expand Up @@ -79,11 +79,25 @@ public HttpTestSetup RespondWithJson(object body, int status = 200, object heade
/// <param name="cookies">The simulated response cookies. Optional.</param>
/// <param name="replaceUnderscoreWithHyphen">If true, underscores in property names of headers will be replaced by hyphens. Default is true.</param>
/// <returns>The current HttpTest object (so more responses can be chained).</returns>
public HttpTestSetup RespondWith(Func<HttpContent> buildContent = null, int status = 200, object headers = null, object cookies = null, bool replaceUnderscoreWithHyphen = true) {
_responses.Add(() => {
public HttpTestSetup RespondWith(Func<HttpContent> buildContent, int status = 200, object headers = null, object cookies = null, bool replaceUnderscoreWithHyphen = true)
{
return RespondWith(request => buildContent?.Invoke(), status, headers, cookies, replaceUnderscoreWithHyphen);
}

/// <summary>
/// Adds a fake HTTP response to the response queue.
/// </summary>
/// <param name="buildContent">A function that builds the simulated response body content. Optional.</param>
/// <param name="status">The simulated HTTP status. Optional. Default is 200.</param>
/// <param name="headers">The simulated response headers. Optional.</param>
/// <param name="cookies">The simulated response cookies. Optional.</param>
/// <param name="replaceUnderscoreWithHyphen">If true, underscores in property names of headers will be replaced by hyphens. Default is true.</param>
/// <returns>The current HttpTest object (so more responses can be chained).</returns>
public HttpTestSetup RespondWith(Func<HttpRequestMessage, HttpContent> buildContent = null, int status = 200, object headers = null, object cookies = null, bool replaceUnderscoreWithHyphen = true) {
return RespondWith(request => {
var response = new HttpResponseMessage {
StatusCode = (HttpStatusCode)status,
Content = buildContent?.Invoke()
Content = buildContent?.Invoke(request)
};

if (headers != null) {
Expand All @@ -99,14 +113,23 @@ public HttpTestSetup RespondWith(Func<HttpContent> buildContent = null, int stat
}
return response;
});
}

/// <summary>
/// Adds a fake HTTP response to the response queue.
/// </summary>
/// <param name="buildResponse">A function that builds the simulated response.</param>
/// <returns>The current HttpTest object (so more responses can be chained).</returns>
public HttpTestSetup RespondWith(Func<HttpRequestMessage, HttpResponseMessage> buildResponse) {
_responses.Add(buildResponse);
return this;
}

/// <summary>
/// Adds a simulated timeout response to the response queue.
/// </summary>
public HttpTestSetup SimulateTimeout() {
_responses.Add(() => new TimeoutResponseMessage());
_responses.Add(request => new TimeoutResponseMessage());
return this;
}

Expand Down

0 comments on commit eb0c043

Please sign in to comment.