-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Make IResult methods more testable #37502
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This is probably not the most appropriate place to ask this question, but the repo doesn't have discussions enabled. Could anyone elaborate why |
IActionResult - Tied to ActionContext (requires another allocation per request and is tied to other things like an ActionDescriptor) I don't think we can unify these types but we can make IResult work in both places. |
We already did that for many of the existing |
Thanks @davidfowl . I guess this naturally leads to my next question: what prevented At first glance, it feels incredibly weird to see |
We wanted something lower level that doesn't pull in ActionDescriptors and doesn't rely on any of the MVC namespaces. We rebuilt MVC on top of endpoint routing in .NET Core 3.1 and this is a continuation of moving primitives out of MVC and into the core platform. There will be some inconveniences for sure (like the ones this issue describes) but those are typical growing pains because MVC was first. This is the reality when trying to retrofit an existing universe on top of a new core. We don't have it written down publicly but there is a north start where MVC is an extensible framework built on top of endpoint routing and route metadata. When it was created, MVC got all of the goodies (routing, model binding, action results, filters) and now we're slowly peeling back those features into the core frameworks so other parts of the stack can benefit from them |
Very interesting @davidfowl . I'd love to read more about these long-term goals for MVC someday, hopefully a blog post will be considered. I noticed that attempting to use I'd also imagine these simpler models won't work with abstractions such as The new types seems much more lightweight as you suggested, so I figured there would be a plan for migrating towards them, but this doesn't appear to be the case, at least not currently. |
This is something we plan to support. It's currently being tracked by #33403 |
Fixed by #40704 |
Is your feature request related to a problem? Please describe.
When you are defining minimal route handlers using named methods instead of lambdas for better unit testability the inability to inspect the state of the
IResult
s returned by the methods in Results makes unit testing far more difficult.Endpoint definition
Broken Test Code
While an endpoint like this can be tested using
WebApplicationFactory
as described here, this is more of a end-to-end test than a unit test as this also tests host initialization and the entire middleware pipeline. While it's possible to replace services with mocks this way, it's far more involved than just callingGetTodo(TodoDb db, int id)
in a test directly as follows.This test will result in an
InvalidCastException
because the Microsoft.AspNetCore.Http.Result.OkObjectResult
returned byResults.Ok(todo)
is internal unlikeMicrosoft.AspNetCore.Mvc.OkObjectResult
.Working Test Code
It is possible to write a similar test by executing
IResult.ExecuteAsync(HttpContext)
with a mockHttpContext
, but it is far more involved.Describe the solution you'd like
We should consider making the IResult implementations in the
Microsoft.AspNetCore.Http.Result
public so theIResult
s returned by theResults
methods can be casted to something that can be inspected by unit tests similar to the MVCActionResult
types.However, we should consider how this might create more confusion for developers using both MVC and minimal route handlers about which result types should be used when. For example, having multiple public
OkObjectResult
implementations in different namespaces could make it hard to determine whichOkObjectResult
to use when. Different names might mitigate the confusion but I doubt it would eliminate it. This kind of concern is why we made MVCFrom*Attribute
s like[FromServices]
work with minimal route handler parameters instead of introducing new parameter attributes.It also might be unclear if you should call the constructor of the newly-public result types or use the existing
IResult
methods. We could keep the constructors internal, but that might be unnecessarily restrictive.Since minimal route handlers do not support content negotiation, having separate public
ObjectResult
andJsonResult
types might be unnecessary.Additional context
Thank you @Elfocrash for demonstrating this issue in your video at https://www.youtube.com/watch?v=VuFQtyRmS0E
The text was updated successfully, but these errors were encountered: