Skip to content

Commit feabb32

Browse files
authored
Update for v4.0.0 (#20)
* Update to use new HttpRequestMessage for each send operation * Add final ConfigureAwait(false)
1 parent afce371 commit feabb32

27 files changed

+2105
-841
lines changed

README.md

+1-433
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
using FluentHttpClient.Tests.Models;
2+
using Microsoft.Extensions.Configuration;
3+
using Microsoft.Extensions.DependencyInjection;
4+
5+
namespace FluentHttpClient.Tests;
6+
7+
public class ClientUnitTests : UnitTestBase
8+
{
9+
private readonly HttpClient _client;
10+
11+
private readonly int MaxPostId = 100;
12+
private readonly int MinPostId = 1;
13+
private readonly int MaxUserId = 10;
14+
private readonly int MinUserId = 1;
15+
private readonly int PostsPerUser = 10;
16+
17+
public ClientUnitTests()
18+
{
19+
_client = GetRequiredService<HttpClient>();
20+
_client.BaseAddress = new Uri("https://jsonplaceholder.typicode.com");
21+
}
22+
23+
protected override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
24+
{
25+
services.AddHttpClient();
26+
}
27+
28+
[Fact]
29+
public async Task OnFailureTest()
30+
{
31+
var route = $"/posts";
32+
var passed = false;
33+
34+
await _client.UsingRoute(route)
35+
.DeleteAsync()
36+
.OnFailure(msg =>
37+
{
38+
passed = true;
39+
})
40+
.OnSuccess(msg =>
41+
{
42+
throw new Exception("The request returned a success status code.");
43+
});
44+
45+
passed.ShouldBeTrue();
46+
}
47+
48+
[Fact]
49+
public async Task OnSuccessTest()
50+
{
51+
var postId = Random.Shared.Next(MinPostId, MaxPostId);
52+
var route = $"/posts/{postId}";
53+
var passed = false;
54+
55+
await _client.UsingRoute(route)
56+
.DeleteAsync()
57+
.OnFailure(msg =>
58+
{
59+
throw new Exception("The request did not return a success status code.");
60+
})
61+
.OnSuccess(msg =>
62+
{
63+
passed = true;
64+
});
65+
66+
passed.ShouldBeTrue();
67+
}
68+
69+
[Fact]
70+
public async Task DefaultActionTest()
71+
{
72+
var route = $"/post/1";
73+
var passed = false;
74+
75+
var builder = _client.UsingRoute(route);
76+
77+
var response = await builder
78+
.GetAsync();
79+
80+
var post1 = await response.DeserializeJsonAsync<Post>();
81+
var post2 = await response.DeserializeJsonAsync<Post>((msg, ex) =>
82+
{
83+
passed = true;
84+
return (Post)null;
85+
});
86+
87+
post1.ShouldNotBeNull();
88+
post2.ShouldBeNull();
89+
passed.ShouldBeTrue();
90+
}
91+
92+
[Fact]
93+
public async Task GetAllAsyncTest()
94+
{
95+
var route = "/posts";
96+
97+
var builder = _client.UsingRoute(route);
98+
99+
var response = await builder.GetAsync();
100+
101+
response.EnsureSuccessStatusCode();
102+
103+
var posts = await response
104+
.DeserializeJsonAsync<IEnumerable<Post>>();
105+
106+
posts.ShouldNotBeNull();
107+
posts.ShouldNotBeEmpty();
108+
posts.Count().ShouldBe(MaxPostId);
109+
}
110+
111+
[Fact]
112+
public async Task GetPostsForUserAsyncTest()
113+
{
114+
var userId = Random.Shared.Next(MinUserId, MaxUserId);
115+
var route = $"/posts";
116+
117+
var builder = _client.UsingRoute(route);
118+
119+
builder.WithQueryParam("userId", userId);
120+
121+
var response = await builder.GetAsync();
122+
123+
response.EnsureSuccessStatusCode();
124+
125+
var posts = await response
126+
.DeserializeJsonAsync<IEnumerable<Post>>();
127+
128+
posts.ShouldNotBeNull();
129+
posts.ShouldNotBeEmpty();
130+
posts.Count().ShouldBe(PostsPerUser);
131+
posts.All(x => x.UserId == userId).ShouldBeTrue();
132+
}
133+
134+
[Fact]
135+
public async Task GetPostByIdAsyncTest()
136+
{
137+
var postId = Random.Shared.Next(MinPostId, MaxPostId);
138+
var route = $"/posts/{postId}";
139+
140+
var builder = _client.UsingRoute(route);
141+
142+
var response = await builder.GetAsync();
143+
144+
response.EnsureSuccessStatusCode();
145+
146+
var post = await response
147+
.DeserializeJsonAsync<Post>();
148+
149+
post.ShouldNotBeNull();
150+
post.Id.ShouldBe(postId);
151+
}
152+
153+
[Fact]
154+
public async Task DeletePostAsync()
155+
{
156+
var postId = Random.Shared.Next(MinPostId, MaxPostId);
157+
var route = $"/posts/{postId}";
158+
159+
var builder = _client.UsingRoute(route);
160+
161+
var response = await builder.DeleteAsync();
162+
163+
response.EnsureSuccessStatusCode();
164+
}
165+
166+
[Fact]
167+
public async Task CreatePostAsync()
168+
{
169+
var post = new Post
170+
{
171+
Id = 0,
172+
UserId = Random.Shared.Next(MinUserId, MaxUserId),
173+
Title = Guid.NewGuid().ToString(),
174+
Body = Guid.NewGuid().ToString()
175+
};
176+
177+
var newPost = await _client
178+
.UsingRoute("/posts")
179+
.WithJsonContent(post)
180+
.PostAsync()
181+
.DeserializeJsonAsync<Post>();
182+
183+
newPost.ShouldNotBeNull();
184+
newPost.ShouldSatisfyAllConditions
185+
(
186+
() => newPost.Id.ShouldBe(MaxPostId + 1),
187+
() => newPost.UserId.ShouldBe(post.UserId),
188+
() => newPost.Title.ShouldBe(post.Title),
189+
() => newPost.Body.ShouldBe(post.Body)
190+
);
191+
}
192+
193+
[Fact]
194+
public async Task UpdatePostAsync()
195+
{
196+
var expected = new Post
197+
{
198+
Id = Random.Shared.Next(MinPostId, MaxPostId),
199+
UserId = Random.Shared.Next(MinUserId, MaxUserId),
200+
Title = Guid.NewGuid().ToString(),
201+
Body = Guid.NewGuid().ToString()
202+
};
203+
204+
var route = $"/posts/{expected.Id}";
205+
var builder = _client.UsingRoute(route);
206+
207+
builder.WithJsonContent(expected);
208+
209+
var response = await builder.PutAsync();
210+
211+
response.EnsureSuccessStatusCode();
212+
213+
var actual = await response
214+
.DeserializeJsonAsync<Post>();
215+
216+
actual.ShouldNotBeNull();
217+
actual.ShouldSatisfyAllConditions
218+
(
219+
() => actual.Id.ShouldBe(expected.Id),
220+
() => actual.UserId.ShouldBe(expected.UserId),
221+
() => actual.Title.ShouldBe(expected.Title),
222+
() => actual.Body.ShouldBe(expected.Body)
223+
);
224+
}
225+
}

src/FluentHttpClient.Tests/FluentHttpClient.Tests.csproj

+11-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
<TargetFramework>net8.0</TargetFramework>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
7-
87
<IsPackable>false</IsPackable>
98
<IsTestProject>true</IsTestProject>
9+
<NoWarn>$(NoWarn);CS8600;CS8603</NoWarn>
1010
</PropertyGroup>
1111

1212
<ItemGroup>
@@ -23,8 +23,18 @@
2323
</PackageReference>
2424
</ItemGroup>
2525

26+
<ItemGroup>
27+
<FrameworkReference Include="Microsoft.AspNetCore.App" />
28+
</ItemGroup>
29+
2630
<ItemGroup>
2731
<ProjectReference Include="..\FluentHttpClient\FluentHttpClient.csproj" />
2832
</ItemGroup>
2933

34+
<ItemGroup>
35+
<None Update="appsettings.json">
36+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
37+
</None>
38+
</ItemGroup>
39+
3040
</Project>
+2-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
global using Xunit;
1+
global using Xunit;
2+
global using Shouldly;
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace FluentHttpClient.Tests.Models;
2+
3+
public class Post
4+
{
5+
public int UserId { get; set; }
6+
7+
public int Id { get; set; }
8+
9+
public string Title { get; set; } = null!;
10+
11+
public string Body { get; set; } = null!;
12+
}

src/FluentHttpClient.Tests/NullHttpResponseMessageTests.cs

-20
This file was deleted.

src/FluentHttpClient.Tests/QueryParamsTests.cs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Collections.Specialized;
12
using Shouldly;
23

34
namespace FluentHttpClient.Tests;
@@ -11,14 +12,14 @@ public void DoesNotRemoveEmptyValues()
1112

1213
var expected = "?name=bob&age=&color=blue";
1314

14-
var qp = new QueryParams
15+
var qp = new NameValueCollection
1516
{
1617
{ "name", "bob" },
1718
{ "age", "" },
1819
{ "color", "blue" }
1920
};
2021

21-
var actual = qp.ToString();
22+
var actual = qp.ToQueryString();
2223
actual.ShouldBe(expected);
2324
}
2425

@@ -29,14 +30,14 @@ public void RemovesEmptyValues()
2930

3031
var expected = "?name=bob&color=blue";
3132

32-
var qp = new QueryParams
33+
var qp = new NameValueCollection
3334
{
3435
{ "name", "bob" },
3536
{ "age", "" },
3637
{ "color", "blue" }
3738
};
3839

39-
var actual = qp.ToString();
40+
var actual = qp.ToQueryString();
4041
actual.ShouldBe(expected);
4142
}
4243
}

0 commit comments

Comments
 (0)