Skip to content

Commit 576bcb6

Browse files
committed
fix flaky tests
1 parent 8227a91 commit 576bcb6

12 files changed

Lines changed: 159 additions & 85 deletions

test/FluentRest.Tests/FluentEchoTests.cs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.IO;
43
using System.IO.Compression;
54
using System.Net;
65
using System.Net.Http;
76
using System.Net.Http.Headers;
87
using System.Text;
98
using System.Text.Json;
10-
using System.Text.Json.Serialization;
119
using System.Threading;
1210
using System.Threading.Tasks;
1311

12+
using Microsoft.Extensions.DependencyInjection;
13+
1414
using Xunit;
15+
using Xunit.Abstractions;
1516

1617
namespace FluentRest.Tests;
1718

18-
public class FluentEchoTests
19+
public class FluentEchoTests : HostTestBase
1920
{
21+
public FluentEchoTests(ITestOutputHelper output, HostFixture fixture)
22+
: base(output, fixture)
23+
{
24+
}
25+
2026
[Fact]
2127
public async Task EchoGet()
2228
{
@@ -29,7 +35,7 @@ public async Task EchoGet()
2935
);
3036

3137
Assert.NotNull(result);
32-
Assert.Equal("https://httpbin.org/get?page=1&size=10", result.Url);
38+
Assert.Equal($"{Fixture.HttpBinUrl}/get?page=1&size=10", result.Url);
3339
Assert.Equal("1", result.QueryString["page"]);
3440
Assert.Equal("10", result.QueryString["size"]);
3541
}
@@ -47,7 +53,7 @@ public async Task EchoGetBearer()
4753
);
4854

4955
Assert.NotNull(result);
50-
Assert.Equal("https://httpbin.org/get?page=1&size=10", result.Url);
56+
Assert.Equal($"{Fixture.HttpBinUrl}/get?page=1&size=10", result.Url);
5157
Assert.Equal("1", result.QueryString["page"]);
5258
Assert.Equal("10", result.QueryString["size"]);
5359

@@ -104,7 +110,7 @@ public async Task EchoGetAcceptMultiple()
104110
);
105111

106112
Assert.NotNull(result);
107-
Assert.Equal("https://httpbin.org/get?page=10", result.Url);
113+
Assert.Equal($"{Fixture.HttpBinUrl}/get?page=10", result.Url);
108114
Assert.Equal("text/xml, application/bson, application/json", result.Headers[HttpRequestHeaders.Accept]);
109115
Assert.Equal("testing header", result.Headers["X-Blah"]);
110116
}
@@ -122,7 +128,7 @@ public async Task EchoPost()
122128
);
123129

124130
Assert.NotNull(result);
125-
Assert.Equal("https://httpbin.org/post?page=10", result.Url);
131+
Assert.Equal($"{Fixture.HttpBinUrl}/post?page=10", result.Url);
126132
Assert.Equal("Value", result.Form["Test"]);
127133
Assert.Equal("value", result.Form["key"]);
128134
}
@@ -145,7 +151,7 @@ public async Task EchoPostResponse()
145151
var result = await response.DeserializeAsync<EchoResult>();
146152

147153
Assert.NotNull(result);
148-
Assert.Equal("https://httpbin.org/post?page=10", result.Url);
154+
Assert.Equal($"{Fixture.HttpBinUrl}/post?page=10", result.Url);
149155
Assert.Equal("Value", result.Form["Test"]);
150156
Assert.Equal("value", result.Form["key"]);
151157
}
@@ -163,7 +169,7 @@ public async Task EchoPatch()
163169

164170
Assert.NotNull(response);
165171

166-
Assert.Equal("https://httpbin.org/patch?page=10", response.Url);
172+
Assert.Equal($"{Fixture.HttpBinUrl}/patch?page=10", response.Url);
167173
Assert.Equal("Value", response.Form["Test"]);
168174
}
169175

@@ -184,7 +190,7 @@ public async Task EchoPatchResponse()
184190
var result = await response.DeserializeAsync<EchoResult>();
185191

186192
Assert.NotNull(result);
187-
Assert.Equal("https://httpbin.org/patch?page=10", result.Url);
193+
Assert.Equal($"{Fixture.HttpBinUrl}/patch?page=10", result.Url);
188194
Assert.Equal("Value", result.Form["Test"]);
189195
}
190196

@@ -201,7 +207,7 @@ public async Task EchoPut()
201207
);
202208

203209
Assert.NotNull(result);
204-
Assert.Equal("https://httpbin.org/put?page=10", result.Url);
210+
Assert.Equal($"{Fixture.HttpBinUrl}/put?page=10", result.Url);
205211
Assert.Equal("Value", result.Form["Test"]);
206212
Assert.Equal("value", result.Form["key"]);
207213
}
@@ -238,7 +244,7 @@ public async Task EchoPostData()
238244
Assert.True(result.Headers.ContainsKey("Content-Length"));
239245
int contentLength = Int32.Parse(result.Headers["Content-Length"]);
240246
Assert.True(contentLength > 0);
241-
Assert.Equal("https://httpbin.org/post?page=10", result.Url);
247+
Assert.Equal($"{Fixture.HttpBinUrl}/post?page=10", result.Url);
242248
Assert.Equal("application/json; charset=utf-8", result.Headers[HttpRequestHeaders.ContentType]);
243249
Assert.True(result.Headers.ContainsKey("Content-Type"));
244250
var contentType = result.Headers["Content-Type"];
@@ -359,7 +365,7 @@ public async Task EchoPostDataCustomCompressedContent()
359365
Assert.True(result.Headers.ContainsKey("Content-Length"));
360366
int contentLength = Int32.Parse(result.Headers["Content-Length"]);
361367
Assert.True(contentLength > 0);
362-
Assert.Equal("https://httpbin.org/post?page=10", result.Url);
368+
Assert.Equal($"{Fixture.HttpBinUrl}/post?page=10", result.Url);
363369
Assert.Equal("application/json; charset=utf-8", result.Headers[HttpRequestHeaders.ContentType]);
364370
Assert.Equal("gzip", result.Headers[HttpRequestHeaders.ContentEncoding]);
365371
}
@@ -416,7 +422,7 @@ public async Task DefaultPost()
416422
);
417423

418424
Assert.NotNull(result);
419-
Assert.Equal("https://httpbin.org/post?page=10", result.Url);
425+
Assert.Equal($"{Fixture.HttpBinUrl}/post?page=10", result.Url);
420426
Assert.Equal("Value", result.Form["Test"]);
421427
Assert.Equal("value", result.Form["key"]);
422428
Assert.Equal("Token abc-def-123", result.Headers["Authorization"]);
@@ -434,15 +440,16 @@ public async Task SendRequest()
434440

435441
Assert.NotNull(result);
436442
Assert.True(result.Headers.ContainsKey("Content-Length"));
437-
Assert.Equal("https://httpbin.org/post", result.Url);
443+
Assert.Equal($"{Fixture.HttpBinUrl}/post", result.Url);
438444
}
439445

440-
private static IFluentClient CreateClient()
446+
private IFluentClient CreateClient()
441447
{
442-
var httpClient = new HttpClient();
443-
httpClient.BaseAddress = new Uri("https://httpbin.org/", UriKind.Absolute);
448+
var httpClientFactory = Services.GetService<IHttpClientFactory>();
449+
var httpClient = httpClientFactory.CreateClient("HttpBin");
444450

445-
var fluentClient = new FluentClient(httpClient);
451+
var serializer = Services.GetService<IContentSerializer>();
452+
var fluentClient = new FluentClient(httpClient, serializer);
446453

447454
return fluentClient;
448455
}

test/FluentRest.Tests/FluentRest.Tests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
1515
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
1616
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
17+
<PackageReference Include="Testcontainers" Version="3.8.0" />
18+
<PackageReference Include="XUnit.Hosting" Version="1.7.0" />
1719
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.1">
1820
<PrivateAssets>all</PrivateAssets>
1921
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>

test/FluentRest.Tests/GitHub/GitHubFactoryTests.cs

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,25 @@
1-
using System;
21
using System.Collections.Generic;
3-
using System.Text.Json;
42
using System.Threading.Tasks;
53

64
using FluentRest.Tests.GitHub.Models;
75

86
using Microsoft.Extensions.DependencyInjection;
97

108
using Xunit;
9+
using Xunit.Abstractions;
1110

1211
namespace FluentRest.Tests.GitHub;
1312

14-
public class GitHubFactoryTests
13+
public class GitHubFactoryTests : HostTestBase
1514
{
16-
public IServiceProvider ServiceProvider { get; }
17-
18-
public GitHubFactoryTests()
15+
public GitHubFactoryTests(ITestOutputHelper output, HostFixture fixture) : base(output, fixture)
1916
{
20-
var services = new ServiceCollection();
21-
22-
services.AddSingleton<IContentSerializer>(sp => new JsonContentSerializer(new JsonSerializerOptions(JsonSerializerDefaults.Web)));
23-
24-
services.AddHttpClient<GithubClient>(c =>
25-
{
26-
c.BaseAddress = new Uri("https://api.github.com/");
27-
28-
c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
29-
c.DefaultRequestHeaders.Add("User-Agent", "GitHubClient");
30-
})
31-
.AddHttpMessageHandler(() => new RetryHandler());
32-
33-
ServiceProvider = services.BuildServiceProvider();
3417
}
3518

3619
[Fact]
3720
public async Task GetRepo()
3821
{
39-
var client = ServiceProvider.GetService<GithubClient>();
22+
var client = Services.GetService<GithubClient>();
4023
var result = await client.GetAsync<Repository>(b => b
4124
.AppendPath("repos")
4225
.AppendPath("loresoft")
@@ -50,7 +33,7 @@ public async Task GetRepo()
5033
[Fact]
5134
public async Task GetRepoIssues()
5235
{
53-
var client = ServiceProvider.GetService<GithubClient>();
36+
var client = Services.GetService<GithubClient>();
5437
var result = await client.GetAsync<List<Issue>>(b => b
5538
.AppendPath("repos")
5639
.AppendPath("loresoft")
@@ -64,7 +47,7 @@ public async Task GetRepoIssues()
6447
[Fact]
6548
public async Task GetFirstIssue()
6649
{
67-
var client = ServiceProvider.GetService<GithubClient>();
50+
var client = Services.GetService<GithubClient>();
6851
var result = await client.GetAsync<Issue>(b => b
6952
.AppendPath("repos")
7053
.AppendPath("loresoft")
Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
1-
using System;
21
using System.Collections.Generic;
3-
using System.Net.Http;
42
using System.Threading.Tasks;
53

64
using FluentRest.Tests.GitHub.Models;
75

6+
using Microsoft.Extensions.DependencyInjection;
7+
88
using Xunit;
9+
using Xunit.Abstractions;
910

1011
namespace FluentRest.Tests.GitHub;
1112

12-
public class GitHubTests
13+
public class GitHubTests : HostTestBase
1314
{
15+
public GitHubTests(ITestOutputHelper output, HostFixture fixture) : base(output, fixture)
16+
{
17+
}
18+
1419
[Fact]
1520
public async Task GetRepo()
1621
{
17-
var client = CreateClient();
22+
var client = Services.GetService<GithubClient>();
1823
var result = await client.GetAsync<Repository>(b => b
1924
.AppendPath("repos")
2025
.AppendPath("loresoft")
@@ -28,7 +33,7 @@ public async Task GetRepo()
2833
[Fact]
2934
public async Task GetRepoIssues()
3035
{
31-
var client = CreateClient();
36+
var client = Services.GetService<GithubClient>();
3237
var result = await client.GetAsync<List<Issue>>(b => b
3338
.AppendPath("repos")
3439
.AppendPath("loresoft")
@@ -42,7 +47,7 @@ public async Task GetRepoIssues()
4247
[Fact]
4348
public async Task GetFirstIssue()
4449
{
45-
var client = CreateClient();
50+
var client = Services.GetService<GithubClient>();
4651
var result = await client.GetAsync<Issue>(b => b
4752
.AppendPath("repos")
4853
.AppendPath("loresoft")
@@ -53,16 +58,4 @@ public async Task GetFirstIssue()
5358

5459
Assert.NotNull(result);
5560
}
56-
57-
private static FluentClient CreateClient()
58-
{
59-
var contentSerializer = new JsonContentSerializer();
60-
61-
var httpClient = new HttpClient();
62-
httpClient.BaseAddress = new Uri("https://api.github.com/", UriKind.Absolute);
63-
64-
var fluentClient = new FluentClient(httpClient, contentSerializer);
65-
return fluentClient;
66-
}
67-
6861
}

test/FluentRest.Tests/GitHub/GithubClient.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System;
21
using System.Net.Http;
32

43
namespace FluentRest.Tests.GitHub;

test/FluentRest.Tests/Google/Maps/GoogleTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
using Xunit;
77

8-
namespace FluentRest.Tests;
8+
namespace FluentRest.Tests.Google.Maps;
99

1010
public class GoogleMapsTests
1111
{
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using Xunit;
2+
3+
namespace FluentRest.Tests;
4+
5+
[CollectionDefinition(CollectionName)]
6+
public class HostCollection : ICollectionFixture<HostFixture>
7+
{
8+
public const string CollectionName = nameof(HostCollection);
9+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
4+
using DotNet.Testcontainers.Builders;
5+
6+
using FluentRest.Tests.GitHub;
7+
8+
using Microsoft.Extensions.DependencyInjection;
9+
using Microsoft.Extensions.DependencyInjection.Extensions;
10+
using Microsoft.Extensions.Hosting;
11+
12+
using Xunit;
13+
14+
using XUnit.Hosting;
15+
16+
using IContainer = DotNet.Testcontainers.Containers.IContainer;
17+
18+
namespace FluentRest.Tests;
19+
20+
public class HostFixture : TestApplicationFixture, IAsyncLifetime
21+
{
22+
private readonly IContainer _container = new ContainerBuilder()
23+
.WithImage("kennethreitz/httpbin:latest")
24+
.WithPortBinding(80, true)
25+
.Build();
26+
27+
public async Task InitializeAsync()
28+
{
29+
await _container.StartAsync();
30+
31+
// get container url
32+
HttpBinUrl = $"http://{_container.Hostname}:{_container.GetMappedPublicPort(80)}";
33+
}
34+
35+
public async Task DisposeAsync()
36+
{
37+
await _container.DisposeAsync();
38+
}
39+
40+
public string HttpBinUrl { get; private set; } = "https://httpbin.org/";
41+
42+
protected override void ConfigureApplication(HostApplicationBuilder builder)
43+
{
44+
base.ConfigureApplication(builder);
45+
46+
builder.Services
47+
.TryAddSingleton<IContentSerializer, JsonContentSerializer>();
48+
49+
builder.Services
50+
.AddHttpClient<GithubClient>(c =>
51+
{
52+
c.BaseAddress = new Uri("https://api.github.com/");
53+
54+
c.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
55+
c.DefaultRequestHeaders.Add("User-Agent", "GitHubClient");
56+
})
57+
.AddHttpMessageHandler(() => new RetryHandler());
58+
59+
builder.Services
60+
.AddHttpClient("GoogleMaps", client => client.BaseAddress = new Uri("https://maps.googleapis.com/maps/api/", UriKind.Absolute));
61+
62+
builder.Services
63+
.AddHttpClient("HttpBin", client => client.BaseAddress = new Uri(HttpBinUrl, UriKind.Absolute));
64+
}
65+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Xunit;
2+
using Xunit.Abstractions;
3+
4+
using XUnit.Hosting;
5+
6+
namespace FluentRest.Tests;
7+
8+
[Collection(HostCollection.CollectionName)]
9+
public abstract class HostTestBase : TestHostBase<HostFixture>
10+
{
11+
protected HostTestBase(ITestOutputHelper output, HostFixture fixture)
12+
: base(output, fixture)
13+
{
14+
}
15+
}

0 commit comments

Comments
 (0)