Skip to content

Commit

Permalink
Refactoring tests
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeyzimarev committed Apr 5, 2024
1 parent 8657a8b commit 251aee8
Show file tree
Hide file tree
Showing 41 changed files with 642 additions and 334 deletions.
2 changes: 2 additions & 0 deletions Directory.Packages.props
Expand Up @@ -12,8 +12,10 @@
<MicrosoftTestHostVer>8.0.3</MicrosoftTestHostVer>
</PropertyGroup>
<ItemGroup Label="Runtime dependencies">
<PackageVersion Include="HttpMultipartParser" Version="8.3.0" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="CsvHelper" Version="30.0.1" />
<PackageVersion Include="PolySharp" Version="1.14.1" />
<PackageVersion Include="System.Text.Json" Version="8.0.3" />
<PackageVersion Include="WireMock.Net" Version="1.5.51" />
<PackageVersion Include="WireMock.Net.FluentAssertions" Version="1.5.51" />
Expand Down
2 changes: 1 addition & 1 deletion test/Directory.Build.props
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<IsTestProject>true</IsTestProject>
<IsPackable>false</IsPackable>
<TargetFrameworks>net472;net6.0;net7.0;net8.0</TargetFrameworks>
<TargetFrameworks>net48;net6.0;net7.0;net8.0</TargetFrameworks>
<Nullable>disable</Nullable>
<NoWarn>xUnit1033</NoWarn>
<VSTestLogger>trx%3bLogFileName=$(MSBuildProjectName).trx</VSTestLogger>
Expand Down
Expand Up @@ -5,23 +5,16 @@

namespace RestSharp.Tests.Integrated.Authentication;

[Collection(nameof(TestServerCollection))]
public class AuthenticationTests {
readonly TestServerFixture _fixture;
readonly ITestOutputHelper _output;

public AuthenticationTests(TestServerFixture fixture, ITestOutputHelper output) {
_fixture = fixture;
_output = output;
}
public class AuthenticationTests : IDisposable {
readonly WireMockServer _server = WireMockTestServer.StartTestServer();

[Fact]
public async Task Can_Authenticate_With_Basic_Http_Auth() {
const string userName = "testuser";
const string password = "testpassword";

var client = new RestClient(
_fixture.Server.Url,
_server.Url!,
o => o.Authenticator = new HttpBasicAuthenticator(userName, password)
);
var request = new RestRequest("headers");
Expand All @@ -35,4 +28,6 @@ public class AuthenticationTests {
parts[0].Should().Be(userName);
parts[1].Should().Be(password);
}
}

public void Dispose() => _server.Dispose();
}
13 changes: 6 additions & 7 deletions test/RestSharp.Tests.Integrated/Authentication/OAuth2Tests.cs
Expand Up @@ -3,21 +3,20 @@

namespace RestSharp.Tests.Integrated.Authentication;

[Collection(nameof(TestServerCollection))]
public class OAuth2Tests {
readonly TestServerFixture _fixture;

public OAuth2Tests(TestServerFixture fixture) => _fixture = fixture;

public class OAuth2Tests : IDisposable {
readonly WireMockServer _server = WireMockTestServer.StartTestServer();

[Fact]
public async Task ShouldHaveProperHeader() {
var auth = new OAuth2AuthorizationRequestHeaderAuthenticator("token", "Bearer");
var client = new RestClient(_fixture.Server.Url, o => o.Authenticator = auth);
var client = new RestClient(_server.Url!, o => o.Authenticator = auth);

var response = await client.GetJsonAsync<TestServerResponse[]>("headers");
var authHeader = response!.FirstOrDefault(x => x.Name == KnownHeaders.Authorization);

authHeader.Should().NotBeNull();
authHeader!.Value.Should().Be("Bearer token");
}

public void Dispose() => _server.Dispose();
}
2 changes: 1 addition & 1 deletion test/RestSharp.Tests.Integrated/CompressionTests.cs
Expand Up @@ -8,7 +8,7 @@ public class CompressionTests {
static async Task<byte[]> GetBody(Func<Stream, Stream> getStream, string value) {
using var memoryStream = new MemoryStream();

await using (var stream = getStream(memoryStream)) {
using (var stream = getStream(memoryStream)) {
stream.WriteStringUtf8(value);
}

Expand Down
91 changes: 77 additions & 14 deletions test/RestSharp.Tests.Integrated/CookieTests.cs
@@ -1,19 +1,32 @@
using System.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using RestSharp.Tests.Integrated.Fixtures;
using RestSharp.Tests.Integrated.Server;
using WireMock.Types;
using WireMock.Util;

namespace RestSharp.Tests.Integrated;

[Collection(nameof(TestServerCollection))]
public class CookieTests {
readonly RestClient _client;
readonly string _host;
public sealed class CookieTests : IDisposable {
readonly RestClient _client;
readonly string _host;
readonly WireMockServer _server = WireMockServer.Start();

public CookieTests(TestServerFixture fixture) {
var options = new RestClientOptions(fixture.Server.Url) {
public CookieTests() {
var options = new RestClientOptions(_server.Url!) {
CookieContainer = new CookieContainer()
};
_client = new RestClient(options);
_host = _client.Options.BaseUrl!.Host;

_server
.Given(Request.Create().WithPath("/get-cookies"))
.RespondWith(Response.Create().WithCallback(HandleGetCookies));

_server
.Given(Request.Create().WithPath("/set-cookies"))
.RespondWith(Response.Create().WithCallback(HandleSetCookies));
}

[Fact]
Expand Down Expand Up @@ -49,16 +62,15 @@ public class CookieTests {
response.Content.Should().Be("success");

AssertCookie("cookie1", "value1", x => x == DateTime.MinValue);
FindCookie("cookie2").Should().BeNull("Cookie 2 should vanish as the path will not match");
response.Cookies.Find("cookie2").Should().BeNull("Cookie 2 should vanish as the path will not match");
AssertCookie("cookie3", "value3", x => x > DateTime.Now);
AssertCookie("cookie4", "value4", x => x > DateTime.Now);
FindCookie("cookie5").Should().BeNull("Cookie 5 should vanish as the request is not SSL");
response.Cookies.Find("cookie5").Should().BeNull("Cookie 5 should vanish as the request is not SSL");
AssertCookie("cookie6", "value6", x => x == DateTime.MinValue, true);

Cookie? FindCookie(string name) => response.Cookies!.FirstOrDefault(p => p.Name == name);
return;

void AssertCookie(string name, string value, Func<DateTime, bool> checkExpiration, bool httpOnly = false) {
var c = FindCookie(name)!;
var c = response.Cookies.Find(name)!;
c.Value.Should().Be(value);
c.Path.Should().Be("/");
c.Domain.Should().Be(_host);
Expand All @@ -73,14 +85,65 @@ public class CookieTests {
var response = await _client.ExecuteAsync(request);
response.Content.Should().Be("success");

var notFoundCookie = FindCookie("cookie_empty_domain");
var notFoundCookie = response.Cookies.Find("cookie_empty_domain");
notFoundCookie.Should().BeNull();

var emptyDomainCookieHeader = response.Headers!
.SingleOrDefault(h => h.Name == KnownHeaders.SetCookie && ((string)h.Value!).StartsWith("cookie_empty_domain"));
emptyDomainCookieHeader.Should().NotBeNull();
((string)emptyDomainCookieHeader!.Value!).Should().Contain("domain=;");
}

Cookie? FindCookie(string name) => response.Cookies!.FirstOrDefault(p => p.Name == name);
static ResponseMessage HandleGetCookies(IRequestMessage request) {
var response = request.Cookies!.Select(x => $"{x.Key}={x.Value}").ToArray();
return WireMockTestServer.CreateJson(response);
}

static ResponseMessage HandleSetCookies(IRequestMessage request) {
var cookies = new List<CookieInternal> {
new("cookie1", "value1", new CookieOptions()),
new("cookie2", "value2", new CookieOptions { Path = "/path_extra" }),
new("cookie3", "value3", new CookieOptions { Expires = DateTimeOffset.Now.AddDays(2) }),
new("cookie4", "value4", new CookieOptions { MaxAge = TimeSpan.FromSeconds(100) }),
new("cookie5", "value5", new CookieOptions { Secure = true }),
new("cookie6", "value6", new CookieOptions { HttpOnly = true }),
new("cookie_empty_domain", "value_empty_domain", new CookieOptions { HttpOnly = true, Domain = string.Empty })
};

var response = new ResponseMessage {
Headers = new Dictionary<string, WireMockList<string>>(),
BodyData = new BodyData {
DetectedBodyType = BodyType.String,
BodyAsString = "success"
}
};

var valuesList = new WireMockList<string>();
valuesList.AddRange(cookies.Select(cookie => cookie.Options.GetHeader(cookie.Name, cookie.Value)));
response.Headers.Add(KnownHeaders.SetCookie, valuesList);

return response;
}

record CookieInternal(string Name, string Value, CookieOptions Options);

public void Dispose() {
_client.Dispose();
_server.Dispose();
}
}

static class CookieExtensions {
public static string GetHeader(this CookieOptions self, string name, string value) {
var cookieHeader = new SetCookieHeaderValue((StringSegment)name, (StringSegment)value) {
Domain = (StringSegment)self.Domain,
Path = (StringSegment)self.Path,
Expires = self.Expires,
Secure = self.Secure,
HttpOnly = self.HttpOnly,
MaxAge = self.MaxAge,
SameSite = (Microsoft.Net.Http.Headers.SameSiteMode)self.SameSite
};
return cookieHeader.ToString();
}
}
1 change: 0 additions & 1 deletion test/RestSharp.Tests.Integrated/DefaultParameterTests.cs
Expand Up @@ -4,7 +4,6 @@

namespace RestSharp.Tests.Integrated;

[Collection(nameof(TestServerCollection))]
public sealed class DefaultParameterTests : IDisposable {
readonly WireMockServer _server = WireMockServer.Start();
readonly RequestBodyCapturer _capturer;
Expand Down
8 changes: 4 additions & 4 deletions test/RestSharp.Tests.Integrated/DownloadFileTests.cs
Expand Up @@ -31,7 +31,7 @@ public sealed class DownloadFileTests : IDisposable {
AdvancedResponseWriter = (response, request) => {
var buf = new byte[16];
// ReSharper disable once MustUseReturnValue
response.Content.ReadAsStream().Read(buf, 0, buf.Length);
response.Content.ReadAsStreamAsync().GetAwaiter().GetResult().Read(buf, 0, buf.Length);
tag = Encoding.ASCII.GetString(buf, 6, 4);
return new RestResponse(request);
}
Expand All @@ -52,7 +52,7 @@ public sealed class DownloadFileTests : IDisposable {
public async Task Handles_Binary_File_Download() {
var request = new RestRequest("");
var response = await _client.DownloadDataAsync(request);
var expected = await File.ReadAllBytesAsync(Path.Combine(_path, Path.Combine(LocalPath.Split('/'))));
var expected = File.ReadAllBytes(Path.Combine(_path, Path.Combine(LocalPath.Split('/'))));

Assert.Equal(expected, response);
}
Expand All @@ -73,8 +73,8 @@ public sealed class DownloadFileTests : IDisposable {

Assert.Null(response);

var fromTemp = await File.ReadAllBytesAsync(tempFile);
var expected = await File.ReadAllBytesAsync(Path.Combine(_path, Path.Combine(LocalPath.Split('/'))));
var fromTemp = File.ReadAllBytes(tempFile);
var expected = File.ReadAllBytes(Path.Combine(_path, Path.Combine(LocalPath.Split('/'))));

Assert.Equal(expected, fromTemp);
}
Expand Down
15 changes: 15 additions & 0 deletions test/RestSharp.Tests.Integrated/Fixtures/CookieExtensions.cs
@@ -0,0 +1,15 @@
using System.Net;

namespace RestSharp.Tests.Integrated.Fixtures;

static class CookieExtensions {
public static Cookie? Find(this CookieCollection? cookieCollection, string name) {
if (cookieCollection == null) return null;
for (var i = 0; i < cookieCollection.Count; i++) {
var cookie = cookieCollection[i];
if (cookie.Name == name) return cookie;
}

return null;
}
}
11 changes: 6 additions & 5 deletions test/RestSharp.Tests.Integrated/HttpClientTests.cs
Expand Up @@ -3,20 +3,21 @@

namespace RestSharp.Tests.Integrated;

[Collection(nameof(TestServerCollection))]
public class HttpClientTests(TestServerFixture fixture) {
public class HttpClientTests : IDisposable {
readonly WireMockServer _server = WireMockTestServer.StartTestServer();

[Fact]
public async Task ShouldUseBaseAddress() {
using var httpClient = new HttpClient();
httpClient.BaseAddress = fixture.Server.Url;
httpClient.BaseAddress = new Uri(_server.Url!);
using var client = new RestClient(httpClient);

var request = new RestRequest("success");
var response = await client.ExecuteAsync<Response>(request);
var response = await client.ExecuteAsync<SuccessResponse>(request);

response.StatusCode.Should().Be(HttpStatusCode.OK);
response.Data!.Message.Should().Be("Works!");
}

record Response(string Message);
public void Dispose() => _server.Dispose();
}
17 changes: 13 additions & 4 deletions test/RestSharp.Tests.Integrated/HttpHeadersTests.cs
@@ -1,11 +1,14 @@
using System.Net;
using RestSharp.Tests.Integrated.Server;
using WireMock.Util;

namespace RestSharp.Tests.Integrated;

[Collection(nameof(TestServerCollection))]
public class HttpHeadersTests(TestServerFixture fixture) {
readonly RestClient _client = new(new RestClientOptions(fixture.Server.Url) { ThrowOnAnyError = true });
public class HttpHeadersTests : IDisposable {
readonly WireMockServer _server = WireMockTestServer.StartTestServer();
readonly RestClient _client;

public HttpHeadersTests() => _client = new RestClient(new RestClientOptions(_server.Url!) { ThrowOnAnyError = true });

[Fact]
public async Task Ensure_headers_correctly_set_in_the_interceptor() {
Expand Down Expand Up @@ -43,6 +46,7 @@ public class HttpHeadersTests(TestServerFixture fixture) {

// Assert
response.StatusCode.Should().Be(HttpStatusCode.OK);
response.Data.Should().NotBeNull();
var header = response.Data!.First(x => x.Name == headerName);
header.Should().NotBeNull();
header.Value.Should().Be(headerValue);
Expand Down Expand Up @@ -75,7 +79,12 @@ record Header(string Name, string Value);
class HeaderInterceptor(string headerName, string headerValue) : Interceptors.Interceptor {
public override ValueTask BeforeHttpRequest(HttpRequestMessage requestMessage, CancellationToken cancellationToken) {
requestMessage.Headers.Add(headerName, headerValue);
return ValueTask.CompletedTask;
return default;
}
}

public void Dispose() {
_server.Dispose();
_client.Dispose();
}
}

0 comments on commit 251aee8

Please sign in to comment.