From c6ff19254382ff68f63cb06f39c65e7c8aaa89d7 Mon Sep 17 00:00:00 2001 From: crupest Date: Sat, 14 Nov 2020 01:59:44 +0800 Subject: ... --- .../IntegratedTests/HttpResponseAssertions.cs | 136 +++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 BackEnd/Timeline.Tests/IntegratedTests/HttpResponseAssertions.cs (limited to 'BackEnd/Timeline.Tests/IntegratedTests/HttpResponseAssertions.cs') diff --git a/BackEnd/Timeline.Tests/IntegratedTests/HttpResponseAssertions.cs b/BackEnd/Timeline.Tests/IntegratedTests/HttpResponseAssertions.cs new file mode 100644 index 00000000..166cde09 --- /dev/null +++ b/BackEnd/Timeline.Tests/IntegratedTests/HttpResponseAssertions.cs @@ -0,0 +1,136 @@ +using FluentAssertions; +using FluentAssertions.Execution; +using FluentAssertions.Formatting; +using FluentAssertions.Primitives; +using System; +using System.Globalization; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Timeline.Models.Http; + +namespace Timeline.Tests.IntegratedTests +{ + public class HttpResponseMessageValueFormatter : IValueFormatter + { + public bool CanHandle(object value) + { + return value is HttpResponseMessage; + } + + public string Format(object value, FormattingContext context, FormatChild formatChild) + { + string newline = context.UseLineBreaks ? Environment.NewLine : ""; + string padding = new string('\t', context.Depth); + + var res = (HttpResponseMessage)value; + return $"{newline}{padding} Status Code: {res.StatusCode}"; + } + } + + public class HttpResponseMessageAssertions + : ReferenceTypeAssertions + { + static HttpResponseMessageAssertions() + { + Formatter.AddFormatter(new HttpResponseMessageValueFormatter()); + } + + public HttpResponseMessageAssertions(HttpResponseMessage instance) + { + Subject = instance; + } + + protected override string Identifier => "HttpResponseMessage"; + + public AndConstraint HaveStatusCode(int expected, string because = "", params object[] becauseArgs) + { + return HaveStatusCode((HttpStatusCode)expected, because, becauseArgs); + } + + public AndConstraint HaveStatusCode(HttpStatusCode expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion.BecauseOf(because, becauseArgs) + .ForCondition(Subject.StatusCode == expected) + .FailWith("Expected status code of {context:HttpResponseMessage} to be {0}{reason}, but found {1}.", expected, Subject.StatusCode); + return new AndConstraint(this); + } + + public async Task HaveAndGetJsonBodyAsync(string because = "", params object[] becauseArgs) + { + var a = Execute.Assertion.BecauseOf(because, becauseArgs); + + var body = await Subject.ReadBodyAsJsonAsync(); + if (body == 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; + } + + public async Task> HaveJsonBodyAsync(string because = "", params object[] becauseArgs) + { + var a = Execute.Assertion.BecauseOf(because, becauseArgs); + + var body = await Subject.ReadBodyAsJsonAsync(); + if (body == 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 new(Subject, null); + } + return new(Subject, body); + } + } + + public static class AssertionResponseExtensions + { + public static HttpResponseMessageAssertions Should(this HttpResponseMessage instance) + { + return new HttpResponseMessageAssertions(instance); + } + + public static Task HaveAndGetCommonBodyAsync(this HttpResponseMessageAssertions assertions, string because = "", params object[] becauseArgs) + { + return assertions.HaveAndGetJsonBodyAsync(because, becauseArgs); + } + + 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 = 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 Task> HaveAndGetCommonDataBodyAsync(this HttpResponseMessageAssertions assertions, string because = "", params object[] becauseArgs) + { + return assertions.HaveAndGetJsonBodyAsync>(because, becauseArgs); + } + + public static async Task BePutAsync(this HttpResponseMessageAssertions assertions, bool create, string because = "", params object[] becauseArgs) + { + 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 async Task BeDeleteAsync(this HttpResponseMessageAssertions assertions, bool delete, string because = "", params object[] becauseArgs) + { + 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 async Task BeInvalidModelAsync(this HttpResponseMessageAssertions assertions, string? message = null) + { + message = string.IsNullOrEmpty(message) ? "" : ", " + message; + 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); + } + } +} -- cgit v1.2.3