From 6cc6a2580ab611d5e348489623bc8fd3216d4181 Mon Sep 17 00:00:00 2001 From: Mitch Denny Date: Wed, 31 May 2023 13:45:19 +1000 Subject: [PATCH 1/3] Add VerifyResponseJsonBodyAsync to test harness. --- .../test/RequestDelegateFactoryTests.cs | 43 ++++++------- .../RequestDelegateCreationTestBase.cs | 22 ++++++- .../RequestDelegateCreationTests.Responses.cs | 61 +++++++++++++++++++ 3 files changed, 103 insertions(+), 23 deletions(-) diff --git a/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs b/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs index 6b6ade29d8c8..ec21f2cf28a6 100644 --- a/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs +++ b/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs @@ -1343,27 +1343,28 @@ public static IEnumerable ComplexResult } } - [Theory] - [MemberData(nameof(ComplexResult))] - public async Task RequestDelegateWritesComplexReturnValueAsJsonResponseBody(Delegate @delegate) - { - var httpContext = CreateHttpContext(); - var responseBodyStream = new MemoryStream(); - httpContext.Response.Body = responseBodyStream; - - var factoryResult = RequestDelegateFactory.Create(@delegate); - var requestDelegate = factoryResult.RequestDelegate; - - await requestDelegate(httpContext); - - var deserializedResponseBody = JsonSerializer.Deserialize(responseBodyStream.ToArray(), new JsonSerializerOptions - { - PropertyNameCaseInsensitive = true - }); - - Assert.NotNull(deserializedResponseBody); - Assert.Equal("Write even more tests!", deserializedResponseBody!.Name); - } + // TODO: Remove once test is migrated. + //[Theory] + //[MemberData(nameof(ComplexResult))] + //public async Task RequestDelegateWritesComplexReturnValueAsJsonResponseBody(Delegate @delegate) + //{ + // var httpContext = CreateHttpContext(); + // var responseBodyStream = new MemoryStream(); + // httpContext.Response.Body = responseBodyStream; + + // var factoryResult = RequestDelegateFactory.Create(@delegate); + // var requestDelegate = factoryResult.RequestDelegate; + + // await requestDelegate(httpContext); + + // var deserializedResponseBody = JsonSerializer.Deserialize(responseBodyStream.ToArray(), new JsonSerializerOptions + // { + // PropertyNameCaseInsensitive = true + // }); + + // Assert.NotNull(deserializedResponseBody); + // Assert.Equal("Write even more tests!", deserializedResponseBody!.Name); + //} [Fact] public async Task RequestDelegateWritesComplexStructReturnValueAsJsonResponseBody() diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTestBase.cs b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTestBase.cs index 5cbc218f5858..187f5d652f1f 100644 --- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTestBase.cs +++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTestBase.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.IO.Pipelines; +using System.Net.Http; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Loader; @@ -218,12 +219,29 @@ internal HttpContext CreateHttpContextWithBody(Todo requestData, IServiceProvide return httpContext; } - internal static async Task VerifyResponseBodyAsync(HttpContext httpContext, string expectedBody, int expectedStatusCode = 200) + internal static async Task GetResponseBodyAsync(HttpContext httpContext) { var httpResponse = httpContext.Response; httpResponse.Body.Seek(0, SeekOrigin.Begin); var streamReader = new StreamReader(httpResponse.Body); - var body = await streamReader.ReadToEndAsync(); + return await streamReader.ReadToEndAsync(); + } + + internal static async Task VerifyResponseJsonBodyAsync(HttpContext httpContext, Action check, int expectedStatusCode = 200) + { + var body = await GetResponseBodyAsync(httpContext); + var deserializedObject = JsonSerializer.Deserialize(body, new JsonSerializerOptions() + { + PropertyNameCaseInsensitive = true + }); + + Assert.Equal(expectedStatusCode, httpContext.Response.StatusCode); + check(deserializedObject); + } + + internal static async Task VerifyResponseBodyAsync(HttpContext httpContext, string expectedBody, int expectedStatusCode = 200) + { + var body = await GetResponseBodyAsync(httpContext); Assert.Equal(expectedStatusCode, httpContext.Response.StatusCode); Assert.Equal(expectedBody, body); } diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.Responses.cs b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.Responses.cs index 374538e3305c..af9464989920 100644 --- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.Responses.cs +++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.Responses.cs @@ -357,4 +357,65 @@ public async Task SupportsIResultWithExplicitInterfaceImplementation() await VerifyResponseBodyAsync(httpContext, "Already gone!", StatusCodes.Status410Gone); } + + public static IEnumerable ComplexResult + { + get + { + var testAction = """ +app.MapPost("/", () => new Todo() { Name = "Write even more tests!" }); +"""; + + var taskTestAction = """ +app.MapPost("/", () => Task.FromResult(new Todo() { Name = "Write even more tests!" })); +"""; + + var valueTaskTestAction = """ +app.MapPost("/", () => ValueTask.FromResult(new Todo() { Name = "Write even more tests!" })); +"""; + + var staticTestAction = """ +app.MapPost("/", StaticTestAction); +static Todo StaticTestAction() => new Todo() { Name = "Write even more tests!" }; +"""; + + var staticTaskTestAction = """ +app.MapPost("/", StaticTaskTestAction); +static Task StaticTaskTestAction() => Task.FromResult(new Todo() { Name = "Write even more tests!" }); +"""; + + var staticValueTaskTestAction = """ +app.MapPost("/", StaticValueTaskTestAction); +static ValueTask StaticValueTaskTestAction() => ValueTask.FromResult(new Todo() { Name = "Write even more tests!" }); +"""; + + return new List + { + new object[] { testAction }, + new object[] { taskTestAction }, + new object[] { valueTaskTestAction }, + new object[] { staticTestAction }, + new object[] { staticTaskTestAction }, + new object[] { staticValueTaskTestAction } + }; + } + } + + [Theory] + [MemberData(nameof(ComplexResult))] + public async Task RequestDelegateWritesComplexReturnValueAsJsonResponseBody(string source) + { + var (_, compilation) = await RunGeneratorAsync(source); + var endpoint = GetEndpointFromCompilation(compilation); + + var httpContext = CreateHttpContext(); + + await endpoint.RequestDelegate(httpContext); + + await VerifyResponseJsonBodyAsync(httpContext, (todo) => + { + Assert.NotNull(todo); + Assert.Equal("Write even more tests!", todo!.Name); + }); + } } From 16035c1c36747456ee556a39d4709b901d2b92bb Mon Sep 17 00:00:00 2001 From: Mitch Denny Date: Wed, 31 May 2023 13:45:52 +1000 Subject: [PATCH 2/3] Remove commented out old test. --- .../test/RequestDelegateFactoryTests.cs | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs b/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs index ec21f2cf28a6..62e16f0a49f3 100644 --- a/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs +++ b/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs @@ -1343,29 +1343,6 @@ public static IEnumerable ComplexResult } } - // TODO: Remove once test is migrated. - //[Theory] - //[MemberData(nameof(ComplexResult))] - //public async Task RequestDelegateWritesComplexReturnValueAsJsonResponseBody(Delegate @delegate) - //{ - // var httpContext = CreateHttpContext(); - // var responseBodyStream = new MemoryStream(); - // httpContext.Response.Body = responseBodyStream; - - // var factoryResult = RequestDelegateFactory.Create(@delegate); - // var requestDelegate = factoryResult.RequestDelegate; - - // await requestDelegate(httpContext); - - // var deserializedResponseBody = JsonSerializer.Deserialize(responseBodyStream.ToArray(), new JsonSerializerOptions - // { - // PropertyNameCaseInsensitive = true - // }); - - // Assert.NotNull(deserializedResponseBody); - // Assert.Equal("Write even more tests!", deserializedResponseBody!.Name); - //} - [Fact] public async Task RequestDelegateWritesComplexStructReturnValueAsJsonResponseBody() { From 3a9d727d48c3765c9f4eedb7bf26c601b82e33a0 Mon Sep 17 00:00:00 2001 From: Mitch Denny Date: Wed, 31 May 2023 15:46:38 +1000 Subject: [PATCH 3/3] One more test. --- .../test/RequestDelegateFactoryTests.cs | 51 ------------------- .../RequestDelegateCreationTestBase.cs | 3 -- .../RequestDelegateCreationTests.Responses.cs | 23 +++++++++ 3 files changed, 23 insertions(+), 54 deletions(-) diff --git a/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs b/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs index 62e16f0a49f3..1641d1e23481 100644 --- a/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs +++ b/src/Http/Http.Extensions/test/RequestDelegateFactoryTests.cs @@ -1314,57 +1314,6 @@ void TestAction(HttpResponse httpResponse) Assert.Equal(httpContext.Response, httpResponseArgument); } - public static IEnumerable ComplexResult - { - get - { - Todo originalTodo = new() - { - Name = "Write even more tests!" - }; - - Todo TestAction() => originalTodo; - Task TaskTestAction() => Task.FromResult(originalTodo); - ValueTask ValueTaskTestAction() => ValueTask.FromResult(originalTodo); - - static Todo StaticTestAction() => new Todo { Name = "Write even more tests!" }; - static Task StaticTaskTestAction() => Task.FromResult(new Todo { Name = "Write even more tests!" }); - static ValueTask StaticValueTaskTestAction() => ValueTask.FromResult(new Todo { Name = "Write even more tests!" }); - - return new List - { - new object[] { (Func)TestAction }, - new object[] { (Func>)TaskTestAction}, - new object[] { (Func>)ValueTaskTestAction}, - new object[] { (Func)StaticTestAction}, - new object[] { (Func>)StaticTaskTestAction}, - new object[] { (Func>)StaticValueTaskTestAction}, - }; - } - } - - [Fact] - public async Task RequestDelegateWritesComplexStructReturnValueAsJsonResponseBody() - { - var httpContext = CreateHttpContext(); - var responseBodyStream = new MemoryStream(); - httpContext.Response.Body = responseBodyStream; - - var factoryResult = RequestDelegateFactory.Create(() => new TodoStruct(42, "Bob", true)); - var requestDelegate = factoryResult.RequestDelegate; - - await requestDelegate(httpContext); - - var deserializedResponseBody = JsonSerializer.Deserialize(responseBodyStream.ToArray(), new JsonSerializerOptions - { - PropertyNameCaseInsensitive = true - }); - - Assert.Equal(42, deserializedResponseBody.Id); - Assert.Equal("Bob", deserializedResponseBody.Name); - Assert.True(deserializedResponseBody.IsComplete); - } - public static IEnumerable ChildResult { get diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTestBase.cs b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTestBase.cs index 187f5d652f1f..e5fcf36b6385 100644 --- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTestBase.cs +++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTestBase.cs @@ -3,7 +3,6 @@ using System.Globalization; using System.IO.Pipelines; -using System.Net.Http; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Loader; @@ -11,7 +10,6 @@ using System.Text.Json; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http.Features; -using Microsoft.AspNetCore.Http.Json; using Microsoft.AspNetCore.Http.RequestDelegateGenerator; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Testing; @@ -22,7 +20,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyModel; using Microsoft.Extensions.DependencyModel.Resolution; -using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Http.Generators.Tests; diff --git a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.Responses.cs b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.Responses.cs index af9464989920..954cb8886fac 100644 --- a/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.Responses.cs +++ b/src/Http/Http.Extensions/test/RequestDelegateGenerator/RequestDelegateCreationTests.Responses.cs @@ -418,4 +418,27 @@ await VerifyResponseJsonBodyAsync(httpContext, (todo) => Assert.Equal("Write even more tests!", todo!.Name); }); } + + [Fact] + public async Task RequestDelegateWritesComplexStructReturnValueAsJsonResponseBody() + { + var source = """ +app.MapPost("/", () => new TodoStruct(42, "Bob", true, TodoStatus.Done)); +"""; + + var (_, compilation) = await RunGeneratorAsync(source); + var endpoint = GetEndpointFromCompilation(compilation); + + var httpContext = CreateHttpContext(); + + await endpoint.RequestDelegate(httpContext); + + await VerifyResponseJsonBodyAsync(httpContext, (todo) => + { + Assert.Equal(42, todo.Id); + Assert.Equal("Bob", todo.Name); + Assert.True(todo.IsComplete); + Assert.Equal(TodoStatus.Done, todo.Status); + }); + } }