I'm porting a project to the new minimal api of ASP.Net 6.
Right now I have something similar to this:
builder.MapGet("/hello", CiaoCiao);
IResult CiaoCiao()
{
return Results.Ok("Ciao ciao!");
}
The reason for having the endpoint implementation in a separate function is that I want to write a unit test for it. But I'm having the following issue:
How do I get the response value (in this case the string "Ciao ciao!"
) out of the IResult
?
So far I didn't find anything in the official documentation about that. There is a class Microsoft.AspNetCore.Http.Result.OkObjectResult
which I could cast to. But that's internal to AspNetCore
, so it's not accessible from my unit test project.
CodePudding user response:
This isn't possible with ASP.NET Core 6 as all the implementations of IResult
are internal.
This is planned to be improved as part of ASP.NET Core 7.
Integration testing your code via the HTTP interface would be one way of testing your application's endpoints with ASP.NET Core 6 using the WebApplicationFactory<T>
class (docs).
CodePudding user response:
I was able to come up with a workaround using some code in the github issue linked by Martin Costello in his answer:
private static async Task<T?> GetResponseValue<T>(IResult result)
{
var mockHttpContext = new DefaultHttpContext
{
// RequestServices needs to be set so the IResult implementation can log.
RequestServices = new ServiceCollection().AddLogging().BuildServiceProvider(),
Response =
{
// The default response body is Stream.Null which throws away anything that is written to it.
Body = new MemoryStream(),
},
};
await result.ExecuteAsync(mockHttpContext);
// Reset MemoryStream to start so we can read the response.
mockHttpContext.Response.Body.Position = 0;
var jsonOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);
return await JsonSerializer.DeserializeAsync<T>(mockHttpContext.Response.Body, jsonOptions);
}
Ugly, but seems to work.