Skip to content

Commit 0b5b843

Browse files
committed
add FlurlCall to RespondWith
1 parent 363416c commit 0b5b843

File tree

3 files changed

+109
-8
lines changed

3 files changed

+109
-8
lines changed

src/Flurl.Http/FlurlClient.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ public async Task<IFlurlResponse> SendAsync(IFlurlRequest request, HttpCompletio
166166

167167
try {
168168
call.HttpResponseMessage =
169-
HttpTest.Current?.FindSetup(call)?.GetNextResponse() ??
169+
HttpTest.Current?.FindSetup(call)?.GetNextResponse(call.Request) ??
170170
await HttpClient.SendAsync(reqMsg, completionOption, ct).ConfigureAwait(false);
171171

172172
call.HttpResponseMessage.RequestMessage = reqMsg;

src/Flurl.Http/Testing/HttpTestSetup.cs

+52-7
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace Flurl.Http.Testing
1616
/// </summary>
1717
public abstract class HttpTestSetup
1818
{
19-
private readonly List<Func<HttpResponseMessage>> _responses = new();
19+
private readonly List<Func<IFlurlRequest, HttpResponseMessage>> _responses = new();
2020

2121
private int _respIndex = 0;
2222
private bool _allowRealHttp = false;
@@ -34,13 +34,13 @@ protected HttpTestSetup(FlurlHttpSettings settings) {
3434
/// </summary>
3535
public FlurlHttpSettings Settings { get; }
3636

37-
internal HttpResponseMessage GetNextResponse() {
37+
internal HttpResponseMessage GetNextResponse(IFlurlRequest request) {
3838
if (_allowRealHttp)
3939
return null;
4040

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

4545
return new HttpResponseMessage {
4646
StatusCode = HttpStatusCode.OK,
@@ -61,6 +61,20 @@ public HttpTestSetup RespondWith(string body, int status = 200, object headers =
6161
return RespondWith(() => new CapturedStringContent(body), status, headers, cookies, replaceUnderscoreWithHyphen);
6262
}
6363

64+
65+
/// <summary>
66+
/// Adds a fake HTTP response to the response queue.
67+
/// </summary>
68+
/// <param name="buildContent">A function that builds the simulated response body content. Optional.</param>
69+
/// <param name="status">The simulated HTTP status. Default is 200.</param>
70+
/// <param name="headers">The simulated response headers (optional).</param>
71+
/// <param name="cookies">The simulated response cookies (optional).</param>
72+
/// <param name="replaceUnderscoreWithHyphen">If true, underscores in property names of headers will be replaced by hyphens. Default is true.</param>
73+
/// <returns>The current HttpTest object (so more responses can be chained).</returns>
74+
public HttpTestSetup RespondWith(Func<IFlurlRequest, string> buildContent, int status = 200, object headers = null, object cookies = null, bool replaceUnderscoreWithHyphen = true) {
75+
return RespondWith((request) => new CapturedStringContent(buildContent(request)), status, headers, cookies, replaceUnderscoreWithHyphen);
76+
}
77+
6478
/// <summary>
6579
/// Adds a fake HTTP response to the response queue with the given data serialized to JSON as the content body.
6680
/// </summary>
@@ -75,6 +89,37 @@ public HttpTestSetup RespondWithJson(object body, int status = 200, object heade
7589
return RespondWith(() => new CapturedJsonContent(s), status, headers, cookies, replaceUnderscoreWithHyphen);
7690
}
7791

92+
/// <summary>
93+
/// Adds a fake HTTP response to the response queue with the given data serialized to JSON as the content body.
94+
/// </summary>
95+
/// <param name="buildContent">A function that builds the simulated response body content. Optional.</param>
96+
/// <param name="status">The simulated HTTP status. Default is 200.</param>
97+
/// <param name="headers">The simulated response headers (optional).</param>
98+
/// <param name="cookies">The simulated response cookies (optional).</param>
99+
/// <param name="replaceUnderscoreWithHyphen">If true, underscores in property names of headers will be replaced by hyphens. Default is true.</param>
100+
/// <returns>The current HttpTest object (so more responses can be chained).</returns>
101+
public HttpTestSetup RespondWithJson(Func<IFlurlRequest, object> buildContent, int status = 200, object headers = null, object cookies = null, bool replaceUnderscoreWithHyphen = true) {
102+
return RespondWith((request) =>
103+
{
104+
var s = Settings.JsonSerializer.Serialize(buildContent(request));
105+
return new CapturedJsonContent(s);
106+
}, status, headers, cookies, replaceUnderscoreWithHyphen);
107+
}
108+
109+
/// <summary>
110+
/// Adds a fake HTTP response to the response queue.
111+
/// </summary>
112+
/// <param name="buildContent">A function that builds the simulated response body content. Optional.</param>
113+
/// <param name="status">The simulated HTTP status. Optional. Default is 200.</param>
114+
/// <param name="headers">The simulated response headers. Optional.</param>
115+
/// <param name="cookies">The simulated response cookies. Optional.</param>
116+
/// <param name="replaceUnderscoreWithHyphen">If true, underscores in property names of headers will be replaced by hyphens. Default is true.</param>
117+
/// <returns>The current HttpTest object (so more responses can be chained).</returns>
118+
public HttpTestSetup RespondWith(Func<HttpContent> buildContent, int status = 200, object headers = null, object cookies = null, bool replaceUnderscoreWithHyphen = true)
119+
{
120+
return RespondWith(request => buildContent?.Invoke(), status, headers, cookies, replaceUnderscoreWithHyphen);
121+
}
122+
78123
/// <summary>
79124
/// Adds a fake HTTP response to the response queue.
80125
/// </summary>
@@ -84,11 +129,11 @@ public HttpTestSetup RespondWithJson(object body, int status = 200, object heade
84129
/// <param name="cookies">The simulated response cookies. Optional.</param>
85130
/// <param name="replaceUnderscoreWithHyphen">If true, underscores in property names of headers will be replaced by hyphens. Default is true.</param>
86131
/// <returns>The current HttpTest object (so more responses can be chained).</returns>
87-
public HttpTestSetup RespondWith(Func<HttpContent> buildContent = null, int status = 200, object headers = null, object cookies = null, bool replaceUnderscoreWithHyphen = true) {
88-
_responses.Add(() => {
132+
public HttpTestSetup RespondWith(Func<IFlurlRequest, HttpContent> buildContent = null, int status = 200, object headers = null, object cookies = null, bool replaceUnderscoreWithHyphen = true) {
133+
_responses.Add((request) => {
89134
var response = new HttpResponseMessage {
90135
StatusCode = (HttpStatusCode)status,
91-
Content = buildContent?.Invoke()
136+
Content = buildContent?.Invoke(request)
92137
};
93138

94139
if (headers != null) {
@@ -118,7 +163,7 @@ public HttpTestSetup SimulateTimeout() =>
118163
/// </summary>
119164
/// <param name="exception">The exception to throw when the call is simulated.</param>
120165
public HttpTestSetup SimulateException(Exception exception) {
121-
_responses.Add(() => throw exception);
166+
_responses.Add((request) => throw exception);
122167
return this;
123168
}
124169

test/Flurl.Test/Http/TestingTests.cs

+56
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Linq;
33
using System.Net.Http;
44
using System.Net.Sockets;
5+
using System.Text.Json;
56
using System.Threading.Tasks;
67
using Flurl.Http;
78
using Flurl.Http.Testing;
@@ -545,5 +546,60 @@ public async Task can_assert_url_ending_with_question_mark(string actual, string
545546
await actual.GetAsync();
546547
httpTest.ShouldHaveCalled(expected);
547548
}
549+
550+
[Test]
551+
public async Task can_respond_with_request_body_http_content()
552+
{
553+
var httpTest = new HttpTest();
554+
httpTest.RespondWith( (request) =>
555+
{
556+
var httpContent = request.Content.ReadAsStringAsync().Result;
557+
return new StringContent(httpContent);
558+
});
559+
var random = new Random();
560+
var expected = random.Next().ToString();
561+
562+
var response = await "https://api.com/foo".PostStringAsync(expected);
563+
564+
var actual = await response.GetStringAsync();
565+
Assert.AreEqual(expected, actual);
566+
}
567+
568+
[Test]
569+
public async Task can_respond_with_request_body_string()
570+
{
571+
var httpTest = new HttpTest();
572+
httpTest.RespondWith( (request) =>
573+
{
574+
var httpContent = request.Content.ReadAsStringAsync().Result;
575+
return httpContent;
576+
});
577+
var random = new Random();
578+
var expected = random.Next().ToString();
579+
580+
var response = await "https://api.com/foo".PostStringAsync(expected);
581+
582+
var actual = await response.GetStringAsync();
583+
Assert.AreEqual(expected, actual);
584+
}
585+
586+
[Test]
587+
public async Task can_respond_with_request_body_json()
588+
{
589+
var httpTest = new HttpTest();
590+
httpTest.RespondWithJson( (request) =>
591+
{
592+
var jsonString = request.Content.ReadAsStringAsync().Result;
593+
var json = JsonSerializer.Deserialize<int>(jsonString);
594+
return json;
595+
});
596+
var random = new Random();
597+
var expected = random.Next();
598+
599+
var response = await "https://api.com/foo".PostJsonAsync(expected);
600+
601+
var actual = await response.GetJsonAsync<int>();
602+
Assert.AreEqual(expected, actual);
603+
}
548604
}
549605
}

0 commit comments

Comments
 (0)