From bd2462f2bc964839e9b64f167dfa47abb3f9afe6 Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 13 Nov 2020 17:08:20 +0800 Subject: ... --- BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs | 16 ++-- .../Timeline.Tests/Helpers/HttpClientExtensions.cs | 25 ++---- .../Helpers/HttpResponseExtensions.cs | 7 +- .../Helpers/ParameterInfoAssertions.cs | 60 -------------- BackEnd/Timeline.Tests/Helpers/ReflectionHelper.cs | 13 --- .../Timeline.Tests/Helpers/ResponseAssertions.cs | 94 ++++++---------------- BackEnd/Timeline.Tests/Helpers/TestApplication.cs | 4 +- BackEnd/Timeline.Tests/Helpers/TestClock.cs | 2 +- 8 files changed, 43 insertions(+), 178 deletions(-) delete mode 100644 BackEnd/Timeline.Tests/Helpers/ParameterInfoAssertions.cs delete mode 100644 BackEnd/Timeline.Tests/Helpers/ReflectionHelper.cs (limited to 'BackEnd/Timeline.Tests/Helpers') diff --git a/BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs b/BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs index b3709a28..ef230cb0 100644 --- a/BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs +++ b/BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs @@ -17,31 +17,33 @@ namespace Timeline.Tests.Helpers var res = await client.GetAsync(getUrl); res.Should().HaveStatusCode(200); var cacheControlHeader = res.Headers.CacheControl; - cacheControlHeader.NoCache.Should().BeTrue(); + cacheControlHeader.Should().NotBeNull(); + cacheControlHeader!.NoCache.Should().BeTrue(); cacheControlHeader.NoStore.Should().BeFalse(); cacheControlHeader.Private.Should().BeTrue(); cacheControlHeader.Public.Should().BeFalse(); cacheControlHeader.MustRevalidate.Should().BeTrue(); cacheControlHeader.MaxAge.Should().NotBeNull().And.Be(TimeSpan.FromDays(14)); - eTag = res.Headers.ETag; + res.Headers.ETag.Should().NotBeNull(); + eTag = res.Headers.ETag!; } { using var request = new HttpRequestMessage() { - RequestUri = new Uri(client.BaseAddress, getUrl), + RequestUri = new Uri(client.BaseAddress!, getUrl), Method = HttpMethod.Get, }; request.Headers.TryAddWithoutValidation("If-None-Match", "\"dsdfd"); var res = await client.SendAsync(request); - res.Should().HaveStatusCode(HttpStatusCode.BadRequest) - .And.HaveCommonBody(ErrorCodes.Common.Header.IfNonMatch_BadFormat); + await res.Should().HaveStatusCode(HttpStatusCode.BadRequest) + .And.HaveCommonBodyWithCodeAsync(ErrorCodes.Common.Header.IfNonMatch_BadFormat); } { using var request = new HttpRequestMessage() { - RequestUri = new Uri(client.BaseAddress, getUrl), + RequestUri = new Uri(client.BaseAddress!, getUrl), Method = HttpMethod.Get, }; request.Headers.TryAddWithoutValidation("If-None-Match", "\"aaa\""); @@ -52,7 +54,7 @@ namespace Timeline.Tests.Helpers { using var request = new HttpRequestMessage() { - RequestUri = new Uri(client.BaseAddress, getUrl), + RequestUri = new Uri(client.BaseAddress!, getUrl), Method = HttpMethod.Get, }; request.Headers.Add("If-None-Match", eTag.ToString()); diff --git a/BackEnd/Timeline.Tests/Helpers/HttpClientExtensions.cs b/BackEnd/Timeline.Tests/Helpers/HttpClientExtensions.cs index 6513bbe7..47335a22 100644 --- a/BackEnd/Timeline.Tests/Helpers/HttpClientExtensions.cs +++ b/BackEnd/Timeline.Tests/Helpers/HttpClientExtensions.cs @@ -1,5 +1,4 @@ -using Newtonsoft.Json; -using System; +using System; using System.Net.Http; using System.Net.Http.Headers; using System.Net.Mime; @@ -10,41 +9,27 @@ namespace Timeline.Tests.Helpers { public static class HttpClientExtensions { - public static Task PatchAsJsonAsync(this HttpClient client, string url, T body) - { - return client.PatchAsJsonAsync(new Uri(url, UriKind.RelativeOrAbsolute), body); - } - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] - public static Task PatchAsJsonAsync(this HttpClient client, Uri url, T body) - { - return client.PatchAsync(url, new StringContent( - JsonConvert.SerializeObject(body), Encoding.UTF8, MediaTypeNames.Application.Json)); - } - public static Task PutByteArrayAsync(this HttpClient client, string url, byte[] body, string mimeType) { return client.PutByteArrayAsync(new Uri(url, UriKind.RelativeOrAbsolute), body, mimeType); } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] public static Task PutByteArrayAsync(this HttpClient client, Uri url, byte[] body, string mimeType) { - var content = new ByteArrayContent(body); + using var content = new ByteArrayContent(body); content.Headers.ContentLength = body.Length; content.Headers.ContentType = new MediaTypeHeaderValue(mimeType); return client.PutAsync(url, content); } - public static Task PutStringAsync(this HttpClient client, string url, string body, string mimeType = null) + public static Task PutStringAsync(this HttpClient client, string url, string body, string? mimeType = null) { return client.PutStringAsync(new Uri(url, UriKind.RelativeOrAbsolute), body, mimeType); } - [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")] - public static Task PutStringAsync(this HttpClient client, Uri url, string body, string mimeType = null) + public static Task PutStringAsync(this HttpClient client, Uri url, string body, string? mimeType = null) { - var content = new StringContent(body, Encoding.UTF8, mimeType ?? MediaTypeNames.Text.Plain); + using var content = new StringContent(body, Encoding.UTF8, mimeType ?? MediaTypeNames.Text.Plain); return client.PutAsync(url, content); } } diff --git a/BackEnd/Timeline.Tests/Helpers/HttpResponseExtensions.cs b/BackEnd/Timeline.Tests/Helpers/HttpResponseExtensions.cs index 2bd497f1..01497434 100644 --- a/BackEnd/Timeline.Tests/Helpers/HttpResponseExtensions.cs +++ b/BackEnd/Timeline.Tests/Helpers/HttpResponseExtensions.cs @@ -21,15 +21,10 @@ namespace Timeline.Tests.Helpers JsonSerializerOptions.Converters.Add(new JsonDateTimeConverter()); } - public static async Task ReadBodyAsJsonAsync(this HttpResponseMessage response) + public static async Task ReadBodyAsJsonAsync(this HttpResponseMessage response) { var stream = await response.Content.ReadAsStreamAsync(); return await JsonSerializer.DeserializeAsync(stream, JsonSerializerOptions); } - - public static Task ReadBodyAsCommonResponseAsync(this HttpResponseMessage response) - { - return response.ReadBodyAsJsonAsync(); - } } } diff --git a/BackEnd/Timeline.Tests/Helpers/ParameterInfoAssertions.cs b/BackEnd/Timeline.Tests/Helpers/ParameterInfoAssertions.cs deleted file mode 100644 index d3e5a41e..00000000 --- a/BackEnd/Timeline.Tests/Helpers/ParameterInfoAssertions.cs +++ /dev/null @@ -1,60 +0,0 @@ -using FluentAssertions; -using FluentAssertions.Execution; -using FluentAssertions.Formatting; -using FluentAssertions.Primitives; -using System; -using System.Reflection; - -namespace Timeline.Tests.Helpers -{ - public class ParameterInfoValueFormatter : IValueFormatter - { - public bool CanHandle(object value) - { - return value is ParameterInfo; - } - - public string Format(object value, FormattingContext context, FormatChild formatChild) - { - var param = (ParameterInfo)value; - return $"{param.Member.DeclaringType.FullName}.{param.Member.Name}#{param.Name}"; - } - } - - public class ParameterInfoAssertions : ReferenceTypeAssertions - { - static ParameterInfoAssertions() - { - Formatter.AddFormatter(new ParameterInfoValueFormatter()); - } - - public ParameterInfoAssertions(ParameterInfo parameterInfo) - { - Subject = parameterInfo; - } - - protected override string Identifier => "parameter"; - - public AndWhichConstraint BeDecoratedWith(string because = "", params object[] becauseArgs) - where TAttribute : Attribute - { - var attribute = Subject.GetCustomAttribute(false); - - Execute.Assertion - .BecauseOf(because, becauseArgs) - .ForCondition(attribute != null) - .FailWith("Expected {0} {1} to be decorated with {2}{reason}, but that attribute was not found.", - Identifier, Subject, typeof(TAttribute).FullName); - - return new AndWhichConstraint(this, attribute); - } - } - - public static class ParameterInfoAssertionExtensions - { - public static ParameterInfoAssertions Should(this ParameterInfo parameterInfo) - { - return new ParameterInfoAssertions(parameterInfo); - } - } -} diff --git a/BackEnd/Timeline.Tests/Helpers/ReflectionHelper.cs b/BackEnd/Timeline.Tests/Helpers/ReflectionHelper.cs deleted file mode 100644 index 3f6036e3..00000000 --- a/BackEnd/Timeline.Tests/Helpers/ReflectionHelper.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Linq; -using System.Reflection; - -namespace Timeline.Tests.Helpers -{ - public static class ReflectionHelper - { - public static ParameterInfo GetParameter(this MethodInfo methodInfo, string name) - { - return methodInfo.GetParameters().Where(p => p.Name == name).Single(); - } - } -} diff --git a/BackEnd/Timeline.Tests/Helpers/ResponseAssertions.cs b/BackEnd/Timeline.Tests/Helpers/ResponseAssertions.cs index 024732f5..95df3eda 100644 --- a/BackEnd/Timeline.Tests/Helpers/ResponseAssertions.cs +++ b/BackEnd/Timeline.Tests/Helpers/ResponseAssertions.cs @@ -6,9 +6,11 @@ using System; using System.Globalization; using System.Net; using System.Net.Http; +using System.Net.Http.Json; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; +using System.Threading.Tasks; using Timeline.Models.Converters; using Timeline.Models.Http; @@ -27,27 +29,7 @@ namespace Timeline.Tests.Helpers string padding = new string('\t', context.Depth); var res = (HttpResponseMessage)value; - - var builder = new StringBuilder(); - builder.Append($"{newline}{padding} Status Code: {res.StatusCode} ; Body: "); - - try - { - var task = res.Content.ReadAsStringAsync(); - task.Wait(); - var body = task.Result; - if (body.Length > 40) - { - body = body[0..40] + " ..."; - } - builder.Append(body); - } - catch (AggregateException) - { - builder.Append("NOT A STRING."); - } - - return builder.ToString(); + return $"{newline}{padding} Status Code: {res.StatusCode}"; } } @@ -79,41 +61,17 @@ namespace Timeline.Tests.Helpers return new AndConstraint(this); } - public AndWhichConstraint HaveJsonBody(string because = "", params object[] becauseArgs) + public async Task HaveAndGetJsonBodyAsync(string because = "", params object[] becauseArgs) { var a = Execute.Assertion.BecauseOf(because, becauseArgs); - string body; - try - { - var task = Subject.Content.ReadAsStringAsync(); - task.Wait(); - body = task.Result; - } - catch (AggregateException e) - { - a.FailWith("Expected response body of {context:HttpResponseMessage} to be json string{reason}, but failed to read it or it was not a string. Exception is {0}.", e.InnerExceptions); - return new AndWhichConstraint(this, null); - } - - try - { - var options = new JsonSerializerOptions - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase - }; - options.Converters.Add(new JsonStringEnumConverter()); - options.Converters.Add(new JsonDateTimeConverter()); - - var result = JsonSerializer.Deserialize(body, options); - - return new AndWhichConstraint(this, result); - } - catch (JsonException e) + var body = await Subject.ReadBodyAsJsonAsync(); + if (body == null) { - a.FailWith("Expected response body of {context:HttpResponseMessage} to be json string{reason}, but failed to deserialize it. Exception is {0}.", e); - return new AndWhichConstraint(this, null); + a.FailWith("Expected response body of {context:HttpResponseMessage} to be json string of type {0}{reason}, but failed to read it or it was not a valid json string.", typeof(T).FullName); + return default!; } + return body; } } @@ -124,47 +82,45 @@ namespace Timeline.Tests.Helpers return new HttpResponseMessageAssertions(instance); } - public static AndWhichConstraint HaveCommonBody(this HttpResponseMessageAssertions assertions, string because = "", params object[] becauseArgs) + public static Task HaveAndGetCommonBodyAsync(this HttpResponseMessageAssertions assertions, string because = "", params object[] becauseArgs) { - return assertions.HaveJsonBody(because, becauseArgs); + return assertions.HaveAndGetJsonBodyAsync(because, becauseArgs); } - public static void HaveCommonBody(this HttpResponseMessageAssertions assertions, int code, string message = null, params object[] messageArgs) + public static async Task HaveCommonBodyWithCodeAsync(this HttpResponseMessageAssertions assertions, int code, string? message = null, params object[] messageArgs) { message = string.IsNullOrEmpty(message) ? "" : ", " + string.Format(CultureInfo.CurrentCulture, message, messageArgs); - var body = assertions.HaveCommonBody("Response body should be CommonResponse{0}", message).Which; + var body = await assertions.HaveAndGetCommonBodyAsync("Response body should be CommonResponse{0}", message); body.Code.Should().Be(code, "Response body code is not the specified one{0}", message); } - public static AndWhichConstraint> HaveCommonDataBody(this HttpResponseMessageAssertions assertions, string because = "", params object[] becauseArgs) + public static Task> HaveAndGetCommonDataBodyAsync(this HttpResponseMessageAssertions assertions, string because = "", params object[] becauseArgs) { - return assertions.HaveJsonBody>(because, becauseArgs); + return assertions.HaveAndGetJsonBodyAsync>(because, becauseArgs); } - public static void BePut(this HttpResponseMessageAssertions assertions, bool create, string because = "", params object[] becauseArgs) + public static async Task BePutAsync(this HttpResponseMessageAssertions assertions, bool create, string because = "", params object[] becauseArgs) { - var body = assertions.HaveStatusCode(create ? 201 : 200, because, becauseArgs) - .And.HaveJsonBody(because, becauseArgs) - .Which; + var body = await assertions.HaveStatusCode(create ? 201 : 200, because, becauseArgs) + .And.HaveAndGetJsonBodyAsync(because, becauseArgs); body.Code.Should().Be(0); body.Data.Create.Should().Be(create); } - public static void BeDelete(this HttpResponseMessageAssertions assertions, bool delete, string because = "", params object[] becauseArgs) + public static async Task BeDeleteAsync(this HttpResponseMessageAssertions assertions, bool delete, string because = "", params object[] becauseArgs) { - var body = assertions.HaveStatusCode(200, because, becauseArgs) - .And.HaveJsonBody(because, becauseArgs) - .Which; + var body = await assertions.HaveStatusCode(200, because, becauseArgs) + .And.HaveAndGetJsonBodyAsync(because, becauseArgs); body.Code.Should().Be(0); body.Data.Delete.Should().Be(delete); } - public static void BeInvalidModel(this HttpResponseMessageAssertions assertions, string message = null) + public static async Task BeInvalidModelAsync(this HttpResponseMessageAssertions assertions, string message = null) { message = string.IsNullOrEmpty(message) ? "" : ", " + message; - assertions.HaveStatusCode(400, "Invalid Model Error must have 400 status code{0}", message) - .And.HaveCommonBody("Invalid Model Error must have CommonResponse body{0}", message) - .Which.Code.Should().Be(ErrorCodes.Common.InvalidModel, + var body = await assertions.HaveStatusCode(400, "Invalid Model Error must have 400 status code{0}", message) + .And.HaveAndGetCommonBodyAsync("Invalid Model Error must have CommonResponse body{0}", message); + body.Code.Should().Be(ErrorCodes.Common.InvalidModel, "Invalid Model Error must have code {0} in body{1}", ErrorCodes.Common.InvalidModel, message); } diff --git a/BackEnd/Timeline.Tests/Helpers/TestApplication.cs b/BackEnd/Timeline.Tests/Helpers/TestApplication.cs index 33d8b318..da8dea46 100644 --- a/BackEnd/Timeline.Tests/Helpers/TestApplication.cs +++ b/BackEnd/Timeline.Tests/Helpers/TestApplication.cs @@ -17,9 +17,9 @@ namespace Timeline.Tests.Helpers { public TestDatabase Database { get; } - public IHost Host { get; private set; } + public IHost Host { get; private set; } = default!; - public string WorkDir { get; private set; } + public string WorkDir { get; private set; } = default!; public TestApplication() { diff --git a/BackEnd/Timeline.Tests/Helpers/TestClock.cs b/BackEnd/Timeline.Tests/Helpers/TestClock.cs index a04a3eb6..7fa17fbe 100644 --- a/BackEnd/Timeline.Tests/Helpers/TestClock.cs +++ b/BackEnd/Timeline.Tests/Helpers/TestClock.cs @@ -33,7 +33,7 @@ namespace Timeline.Tests.Helpers { if (_currentTime == null) return SetMockCurrentTime(); - _currentTime += timeSpan; + _currentTime = _currentTime.Value + timeSpan; return _currentTime.Value; } } -- cgit v1.2.3