Skip to content

Commit 46e5e26

Browse files
committed
Add some convenience methods to quicly assert for gets and posts and different types of content
1 parent 5851827 commit 46e5e26

7 files changed

Lines changed: 216 additions & 6 deletions

File tree

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<PropertyGroup>
3-
<LangVersion>13.0</LangVersion>
3+
<LangVersion>14.0</LangVersion>
44
<Nullable>enable</Nullable>
55
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
66
<EnableNETAnalyzers>true</EnableNETAnalyzers>

src/TestableHttpClient/HttpRequestMessageAsserter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ public HttpRequestMessageAsserter(IEnumerable<HttpRequestMessage> httpRequestMes
1818
{
1919
Requests = httpRequestMessages ?? throw new ArgumentNullException(nameof(httpRequestMessages));
2020
Options = options ?? new TestableHttpMessageHandlerOptions();
21-
expectedRequestBuilder = new RequestBuilder(Options.UriPatternMatchingOptions);
21+
expectedRequestBuilder = new RequestBuilder(Options);
2222
}
2323

2424
public HttpRequestMessageAsserter(IEnumerable<HttpRequestMessage> httpRequestMessages, Action<RequestBuilder> requestBuilderAction, TestableHttpMessageHandlerOptions? options = null)
2525
{
2626
Requests = httpRequestMessages ?? throw new ArgumentNullException(nameof(httpRequestMessages));
2727
Options = options ?? new TestableHttpMessageHandlerOptions();
28-
expectedRequestBuilder = new RequestBuilder(Options.UriPatternMatchingOptions);
28+
expectedRequestBuilder = new RequestBuilder(Options);
2929
requestBuilderAction?.Invoke(expectedRequestBuilder);
3030
}
3131

src/TestableHttpClient/PublicAPI.Unshipped.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
override TestableHttpClient.TestableHttpMessageHandler.Dispose(bool disposing) -> void
2+
static TestableHttpClient.RequestBuilderExtension.Get(this TestableHttpClient.RequestBuilder! builder, string! pattern) -> TestableHttpClient.RequestBuilder!
3+
static TestableHttpClient.RequestBuilderExtension.Post(this TestableHttpClient.RequestBuilder! builder, string! pattern, string! content) -> TestableHttpClient.RequestBuilder!
4+
static TestableHttpClient.RequestBuilderExtension.PostAsJson(this TestableHttpClient.RequestBuilder! builder, string! pattern, object? content) -> TestableHttpClient.RequestBuilder!
5+
static TestableHttpClient.RequestBuilderExtension.WithFormUrlEncodedContent(this TestableHttpClient.RequestBuilder! builder, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string?, string?>>! formValues) -> TestableHttpClient.RequestBuilder!
6+
static TestableHttpClient.RequestBuilderExtension.WithJsonContent(this TestableHttpClient.RequestBuilder! builder, object? content) -> TestableHttpClient.RequestBuilder!
27
TestableHttpClient.IHttpRequestMessagesCheck.WithContent(string! pattern) -> TestableHttpClient.IHttpRequestMessagesCheck!
38
TestableHttpClient.IHttpRequestMessagesCheck.WithContent(string! pattern, int expectedNumberOfRequests) -> TestableHttpClient.IHttpRequestMessagesCheck!
49
TestableHttpClient.IHttpRequestMessagesCheck.WithHeader(string! headerName) -> TestableHttpClient.IHttpRequestMessagesCheck!
@@ -18,5 +23,6 @@ TestableHttpClient.RequestBuilder.WithHeader(string! headerName, string! pattern
1823
TestableHttpClient.RequestBuilder.WithMethod(System.Net.Http.HttpMethod! httpMethod) -> TestableHttpClient.RequestBuilder!
1924
TestableHttpClient.RequestBuilder.WithRequestUri(string! pattern) -> TestableHttpClient.RequestBuilder!
2025
TestableHttpClient.RequestBuilder.WithVersion(System.Version! httpVersion) -> TestableHttpClient.RequestBuilder!
26+
TestableHttpClient.RequestBuilderExtension
2127
TestableHttpClient.TestableHttpMessageHandler.ShouldHaveMadeRequests(int numberOfRequests, System.Action<TestableHttpClient.RequestBuilder!>! builder) -> void
2228
TestableHttpClient.TestableHttpMessageHandler.ShouldHaveMadeRequests(System.Action<TestableHttpClient.RequestBuilder!>! builder) -> void

src/TestableHttpClient/RequestBuilder.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
public sealed class RequestBuilder
44
{
55
private Request request;
6+
internal TestableHttpMessageHandlerOptions Options { get; }
67

7-
internal RequestBuilder(UriPatternMatchingOptions uriPatternMatchingOptions)
8+
internal RequestBuilder(TestableHttpMessageHandlerOptions? options = null)
89
{
9-
request = new(uriPatternMatchingOptions);
10+
Options = options ?? new();
11+
request = new(Options.UriPatternMatchingOptions);
1012
}
1113

1214
public RequestBuilder WithMethod(HttpMethod httpMethod)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
namespace TestableHttpClient;
2+
3+
public static class RequestBuilderExtension
4+
{
5+
public static RequestBuilder Get(this RequestBuilder builder, string pattern)
6+
{
7+
Guard.ThrowIfNull(builder);
8+
return builder.WithMethod(HttpMethod.Get).WithRequestUri(pattern);
9+
}
10+
11+
public static RequestBuilder Post(this RequestBuilder builder, string pattern, string content)
12+
{
13+
Guard.ThrowIfNull(builder);
14+
return builder.WithMethod(HttpMethod.Post).WithRequestUri(pattern).WithContent(content);
15+
}
16+
17+
public static RequestBuilder PostAsJson(this RequestBuilder builder, string pattern, object? content)
18+
{
19+
Guard.ThrowIfNull(builder);
20+
21+
return builder.WithMethod(HttpMethod.Post).WithRequestUri(pattern).WithJsonContent(content);
22+
}
23+
24+
public static RequestBuilder WithJsonContent(this RequestBuilder builder, object? content)
25+
{
26+
Guard.ThrowIfNull(builder);
27+
28+
string jsonContent = JsonSerializer.Serialize(content, builder.Options.JsonSerializerOptions);
29+
30+
return builder.WithContent(jsonContent).WithHeader("Content-Type", "application/json*");
31+
}
32+
33+
public static RequestBuilder WithFormUrlEncodedContent(this RequestBuilder builder, IEnumerable<KeyValuePair<string?, string?>> formValues)
34+
{
35+
Guard.ThrowIfNull(builder);
36+
37+
using FormUrlEncodedContent content = new(formValues);
38+
string contentString = content.ReadAsStringAsync().Result;
39+
40+
return builder.WithContent(contentString).WithHeader("Content-Type", "application/x-www-form-urlencoded*");
41+
}
42+
}
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
using TestableHttpClient.Utils;
2+
3+
namespace TestableHttpClient.Tests;
4+
5+
public sealed class RequestBuilderExtensionsTests
6+
{
7+
private readonly RequestBuilder sut = new(new());
8+
9+
[Fact]
10+
public void Get_WithNullBuilder_ShouldThrowArgumentNullException()
11+
{
12+
RequestBuilder sut = null!;
13+
Assert.Throws<ArgumentNullException>(() => sut.Get("https://localhost"));
14+
}
15+
16+
[Fact]
17+
public void Get_WithNullRequestUri_ShouldThrowArgumentNullException()
18+
{
19+
Assert.Throws<ArgumentNullException>(() => sut.Get(null!));
20+
}
21+
22+
[Fact]
23+
public void Get_ShouldSetHttpMethodAndRequestUri()
24+
{
25+
Request request = sut.Get("https://localhost").Build();
26+
27+
Assert.Equal(HttpMethod.Get, request.Method);
28+
Assert.Equal(UriPatternParser.Parse("https://localhost"), request.RequestUri);
29+
Assert.Null(request.Version);
30+
Assert.Null(request.Headers);
31+
Assert.Null(request.Content);
32+
}
33+
34+
[Fact]
35+
public void Post_WithNullBuilder_ShouldThrowArgumentNullException()
36+
{
37+
RequestBuilder sut = null!;
38+
Assert.Throws<ArgumentNullException>(() => sut.Post("https://localhost", "{\"hello\":1}"));
39+
}
40+
41+
[Fact]
42+
public void Post_WithNullRequestUri_ShouldThrowArgumentNullException()
43+
{
44+
Assert.Throws<ArgumentNullException>(() => sut.Post(null!, "{\"hello\":1}"));
45+
}
46+
47+
[Fact]
48+
public void Post_WithNullContent_ShouldThrowArgumentNullException()
49+
{
50+
Assert.Throws<ArgumentNullException>(() => sut.Post("https://localhost", null!));
51+
}
52+
53+
[Fact]
54+
public void Post_ShouldBuildCorrectRequest()
55+
{
56+
Request request = sut.Post("https://localhost", "{\"hello\":1}").Build();
57+
58+
Assert.Equal(HttpMethod.Post, request.Method);
59+
Assert.Equal(UriPatternParser.Parse("https://localhost"), request.RequestUri);
60+
Assert.Null(request.Version);
61+
Assert.Null(request.Headers);
62+
Assert.Equal("{\"hello\":1}", request.Content);
63+
}
64+
65+
[Fact]
66+
public void PostAsJson_WithNullBuilder_ShouldThrowArgumentNullException()
67+
{
68+
RequestBuilder sut = null!;
69+
70+
Assert.Throws<ArgumentNullException>(() => sut.PostAsJson("https://localhost", new()));
71+
}
72+
73+
[Fact]
74+
public void PostAsJson_WithNullRequestUri_ShouldThrowArgumentNullException()
75+
{
76+
Assert.Throws<ArgumentNullException>(() => sut.PostAsJson(null!, new()));
77+
}
78+
79+
[Fact]
80+
public void PostAsJson_WithNullContent_ShouldBuildCorrectRequest()
81+
{
82+
Request request = sut.PostAsJson("https://localhost", null).Build();
83+
84+
Assert.Equal(HttpMethod.Post, request.Method);
85+
Assert.Equal(UriPatternParser.Parse("https://localhost"), request.RequestUri);
86+
Assert.Null(request.Version);
87+
Assert.Equivalent(new Dictionary<string, Value>() { ["Content-Type"] = Value.Pattern("application/json*") }, request.Headers);
88+
Assert.Equal("null", request.Content);
89+
}
90+
91+
[Fact]
92+
public void PostAsJson_ShouldBuildCorrectRequest()
93+
{
94+
Request request = sut.PostAsJson("https://localhost", new { hello = 1 }).Build();
95+
96+
Assert.Equal(HttpMethod.Post, request.Method);
97+
Assert.Equal(UriPatternParser.Parse("https://localhost"), request.RequestUri);
98+
Assert.Null(request.Version);
99+
Assert.Equivalent(new Dictionary<string, Value>() { ["Content-Type"] = Value.Pattern("application/json*") }, request.Headers);
100+
Assert.Equal("{\"hello\":1}", request.Content);
101+
}
102+
103+
[Fact]
104+
public void WithJsonContent_WithNullBuilder_ShouldThrowArgumentNullException()
105+
{
106+
RequestBuilder sut = null!;
107+
108+
Assert.Throws<ArgumentNullException>(() => sut.WithJsonContent(new()));
109+
}
110+
111+
[Fact]
112+
public void WithJsonContent_WithNullContent_ShouldBuildCorrectRequest()
113+
{
114+
Request request = sut.WithJsonContent(null).Build();
115+
116+
Assert.Null(request.Method);
117+
Assert.Null(request.RequestUri);
118+
Assert.Null(request.Version);
119+
Assert.Equivalent(new Dictionary<string, Value>() { ["Content-Type"] = Value.Pattern("application/json*") }, request.Headers);
120+
Assert.Equal("null", request.Content);
121+
}
122+
123+
[Fact]
124+
public void WithJsonContent_ShouldBuildCorrectRequest()
125+
{
126+
Request request = sut.WithJsonContent(new { hello = 1 }).Build();
127+
128+
Assert.Null(request.Method);
129+
Assert.Null(request.RequestUri);
130+
Assert.Null(request.Version);
131+
Assert.Equivalent(new Dictionary<string, Value>() { ["Content-Type"] = Value.Pattern("application/json*") }, request.Headers);
132+
Assert.Equal("{\"hello\":1}", request.Content);
133+
}
134+
135+
[Fact]
136+
public void WithFormUrlEncodedContent_WithNullBuilder_ShouldThrowArgumentNullException()
137+
{
138+
RequestBuilder sut = null!;
139+
140+
Assert.Throws<ArgumentNullException>(() => sut.WithFormUrlEncodedContent([]));
141+
}
142+
143+
[Fact]
144+
public void WithFormUrlEncodedContent_WithNullFormValues_ShouldThrowArgumentNullException()
145+
{
146+
Assert.Throws<ArgumentNullException>(() => sut.WithFormUrlEncodedContent(null!));
147+
}
148+
149+
[Fact]
150+
public void WithFormUrlEncodedContent_ShouldBuildCorrectRequest()
151+
{
152+
Request request = sut.WithFormUrlEncodedContent([new KeyValuePair<string?, string?>("username", "alice")]).Build();
153+
154+
Assert.Null(request.Method);
155+
Assert.Null(request.RequestUri);
156+
Assert.Null(request.Version);
157+
Assert.Equivalent(new Dictionary<string, Value>() { ["Content-Type"] = Value.Pattern("application/x-www-form-urlencoded*") }, request.Headers);
158+
Assert.Equal("username=alice", request.Content);
159+
}
160+
}

test/TestableHttpClient.Tests/RequestBuilderTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace TestableHttpClient.Tests;
44

55
public sealed class RequestBuilderTests
66
{
7-
private readonly RequestBuilder sut = new(new UriPatternMatchingOptions());
7+
private readonly RequestBuilder sut = new(new());
88

99
[Fact]
1010
public void Build_ByDefault_CreatesEmptyRequest()

0 commit comments

Comments
 (0)