Can an ASP.NET MVC project with attribute routing be tested? - c#

I've spent days trying to mock, stub and fake my way to a testable application. I usually don't test controller actions, but test all my other classes and patterns instead.
The wall I hit was with the new attribute routing feature. While I can use the routing classes to register my rules etc. I get this error when MapMvcAttributeRoutes is called.
This method cannot be called during the application's pre-start initialization phase
This is discussed here.
MapMvcAttributeRoutes: This method cannot be called during the application's pre-start initialization phase
To be honest, I can't understand the answer(s). Not the code, but its fragmented into versions, links to other bugs, GitHub etc.
I'm a bit lost as to the bottom line answer:
As of 23rd October, 2014. Is it possible to register all routes under test conditions, what version of MVC do I need and which classes/methods do I call to do it?
At present, my classes using UrlHelper are screwing up because needed routes are missing. I am injecting subclasses to bypass the issue, but I don't think its unreasonable to fake the runtime MVC environment and have my app run without lots of DI acrobatics.
It would be nice if these was a simple helper in the framework itself that could take a JSON object describing a raw HTTP request and have the Controller, HttpContext, ControllerContext etc. etc. all created properly as if it were a real request off the wire.
Thanks,
Luke

Good question, and I think that the answer is that little or no thought was given to testing routes in the design of this part of the framework. There may be ways to test routes, but they will be indirect, undocumented and prone to break when a new version of MVC ships.
I have a blog post here on my experiences on the topic. I also suggest that you also campaign for better testability in ASP vNext in the public issue tracker.

During a daily stand-up, a colleague mentioned he was integration testing via an in-memory web server. Intrigued, he showed me how and I was amazed, learnt something :-)
You can new-up an HttpServer instance and have it read your config and then invoke the server instance. I have not tried it, but I see no reason why this wouldn't enumerate your routes and code needing proper config will all work.
This SO question is related and may help in how to set this up:
How does the In-Memory HttpServer know which WebAPI project to host?

Related

What is AddEndpointsApiExplorer in ASP.NET Core 6

I'm upgrading an ASP.NET Core API project from v5 to v6.
Service config in v5:
services.AddSwaggerGen();
Service config in v6:
builder.Services.AddEndpointsApiExplorer(); // what is this?
builder.Services.AddSwaggerGen();
What is AddEndpointsApiExplorer? Everything works as expected whether I add it or not.
I use the "ASP.NET API Versioning" library. Are they related? If so, must I use both, just the library, or is the library unnecessary now?
AddEndpointsApiExplorer is for Minimal APIs whereas AddApiExplorer requires, at least, MVC Core. For API projects, AddControllers calls AddApiExplorer on your behalf.
But Why Does Everything Still Work With AddEndpointsApiExplorer?
With the introduction of Endpoint Routing, everything in the routing system boils down to an Endpoint. ASP.NET Core uses the Application Model, namely ApplicationModel, ControllerModel, and ActionModel, to create Endpoint instances and register them with the routing system. Minimal APIs, however, use a builder to directly create and register individual Endpoint instances.
The default API Explorer implementation provides a IApiDescriptionProvider that builds ApiDescription instances from the Application Model. Minimal APIs do not have an Application Model so there is nothing to build ApiDescription instances from. The API Explorer provides these descriptions, which are commonly used by tools such as OpenAPI generators. Without any descriptions, there would be no support for Minimal APIs and OpenAPI; that would be bad (or, at least, certainly not accepted by developers). To address that, the ASP.NET Core team created a second IApiDescriptionProvider that only considers Endpoint.
If Everything is an Endpoint, Why Not Merge Implementations?
There's two parts to this answer. First, changing the original IApiDescriptionProvider implementation would introduce a public, breaking change. At a minimum, new constructor arguments would be required. Since it was a major version bump, this approach wasn't off the table, but it turns out to be irrelevant. The bigger issue is that the original IApiDescriptionProvider implementation and AddApiExplorer live in and depend on MVC Core. Minimal APIs only require the routing abstractions. There is no way to merge the two without adding unnecessary coupling. To address this problem, AddEndpointsApiExplorer was added which adds an implementation that only requires an IApiDescriptionProvider implementation based on bare bones Endpoint definitions from the routing system.
If AddEndpointsApiExplorer exists and I call it, do I even need AddApiExplorer anymore? Maybe. The metadata exposed and available on Minimal API Endpoint instances is much lighter than the Application Model; after all, they are minimal. Behind the scenes, a IApiDescriptionGroupCollectionProvider implementation takes a sequence of IApiDescriptionProvider instances. If AddEndpointsApiExplorer and AddApiExplorer are called, then both providers will execute. If only AddEndpointsApiExplorer is called, it will work with regular 'ol controllers, but the descriptions' information fidelity might be less than what you are accustomed to. If you are only authoring Minimal APIs, then AddEndpointsApiExplorer is required if you want API Explorer support.
The fidelity between the two methods is improving even more in .NET 7.0. In some future release, it's possible we might see these approaches coalesce into one.
TLDR; .AddEndpointsApiExplorer() was created to support Minimal Api's.
Searching the doc's via google shows a number of pages that include a call to .AddEndpointsApiExplorer(). But no mention of why you need it, or if it is required when migrating from a v5 project. The documentation is definitely lacking.
Working backwards from the source code & git blame, I found the related project. So the answer appears to be related to support for Minimal Api's.
I believe some new services were created to extract return type information from these new minimal api's, in a way that might apply in a more general way when using Endpoint Routing without MVC.
If you are using MVC, perhaps via .AddControllers(), .AddApiExplorer() would be called for you. Providing the services that swagger depends on for describing controller actions. If that's all you need, then this new api call doesn't seem to be required.
While the documentation for using swagger with minimal api's includes a call to .AddEndpointsApiExplorer(). Even that doesn't explain exactly why it is required.
Why does .AddEndpointsApiExplorer() exist at all? Why were the new features excluded from .AddApiExplorer()? Why was this method rename left out of other documentation for v6?
Perhaps we should create an issue on https://github.com/dotnet/aspnetcore/ or https://github.com/dotnet/AspNetCore.Docs/ to ask for clarification so that others don't have to ask these questions.
TL;DR
Only use AddEndpointsApiExplorer if you use v6's "minimal APIs", which look like this:
app.MapGet("/", () => "Hello World!");

Build an API for Multiple

I'm building an API using WebAPI that will be accessed via AJAX calls. However, the API controller will need more than just one POST method. I understand I can specify {action} in my routing, but because I've seen that this is not recommended - am I using the right tool? So 2 questions:
Is Web API the best tool for this, or is there something else I should be using?
Why should I not use more than one POST method in a WebApiController? Is including {action} in my routing a good enough solution to this problem?
1. Is Web API the best tool for this, or is there something else I should be using?
I think WebAPI is a fine choice for you, regardless of whether you have one or many POST calls per controller.
2. Why should I not use more than one POST method in a WebApiController?
To remain RESTFul you'll want a controller per entity type. Without getting too deep into details, a POST against a specific type of entity should be the 'ADD entity' call, and why would you have more than one of those? Having said that, you don't have to be fully RESTFul... if your requirements suite a multi-POST model then go for it, you can always refactor later if necessary.
...Is including {action} in my routing a good enough solution to this problem?
Again, if your goal is to be RESTFul then this isn't a great practice. However, if you have needs that are best achieved using action routings then go for it. REST is not the only model.

Register routes assigned with Attribute Routing at runtime

I am working on the MVC application that loads controller at runtime from an external assembly with MEF and registers routes using custom route handler I have implemented with help of this tutorial:
http://haacked.com/archive/2010/01/17/editable-routes.aspx/
However recently I discovered a powerful features in MVC 5.1, called Attribute Routing.
I would like to know if that is possible to create a custom Attribute Routing that registers Attribute Routing at runtime?
No. This method basically just turns RouteConfig.cs into a runtime-compiled assembly instead of something that's pre-built by the time your application runs. Frankly, I think that is just about one of the most horrible ideas ever. I give credit to the author for being clever enough to figure out how to do something like that. It's a wonderful thought exercise, but as production code: OMFG, no way.
With Attribute Routing, all your routes are in your controllers, so to do the same thing would require making all your controllers individual runtime-compiled assemblies, and that goes beyond scary. Don't do that.

Evaluating MvcContrib TestHelper

For my ASP.NET MVC3 (new) development, I don't want to create a dependency on MvcContrib TestHelper (and thus Rhino Mocks) unless it is providing significant value. So I'm seeking to understand the current status of this helper.
The documentation says that TestHelper produces fakes for the following controller dependencies:
HttpContext
HttpRequest
HttpResponse
HttpSession
Form
TempData
QueryString
ApplicationPath
PathInfo
For MVC1 and MVC2 I can see why this was so helpful. But MVC3 started to introduce improved test "seams" which may have made TestHelper less pertinent. For example, the MVC3 Request and Response controller properties were designed specifically to be isolateable/injectable versions of HttpRequest and HttpResponse.
As I'm still exploring testability advancements in MVC3, I'd like to know how many of the other dependencies listed above have received improved isolation (or injectability) in MVC3. I'd also love to see samples of code showing what it looks like in MVC3 to create tests with fakes (stubs / mocks) for the above dependencies WITH and WITHOUT using TestHelper.
If the differences in test-writing with and without TestHelper are sufficiently marginal, then I'd prefer to forego TestHelper...which means I am then free to choose whatever isolation framework I like (MOQ or NSubstitute).
Ultimately I would be surprised to learn the MVC3 release had taken specific improved testability steps for HttpRequest and HttpResponse, but not for the other above listed dependency issues. I'm hoping someone can give a break-down of how the above items are isolated without using TestHelper.
But MVC3 started to introduce improved test "seams" which may have
made TestHelper less pertinent. For example, the MVC3 Request and
Response controller properties were designed specifically to be
isolateable/injectable versions of HttpRequest and HttpResponse.
MVC didn't introduce absolutely anything new in respect to the objects you have listed in your question in terms of unit testabaility. They were abstractions in ASP.NET MVC 1 and 2 and are abstractions in ASP.NET MVC 3. This allows you to unit test your controller actions and code that depends on them in isolation. But in order to do that you need to mock those dependencies. That's where a mocking framework comes into play. Rhino Mocks is just one possible framework. MVCContrib.TestHelper provides a really nice and fluent syntax to unit test controller actions. Personally I use it all the time. It really makes the unit tests more readable and avoids cluttering them with all kind of plumbing, mocking and infrastructure code.
Check this unit test for example: https://github.com/darind/samplemvc/blob/master/tests/SampleMvc.Web.Tests/Controllers/UsersControllerTests.cs
ASP.NET MVC 3 introduced a dependency resolver and providers which allows you to inject dependencies into many other parts of the framework other than simple controllers and thus unit test those parts which previously were difficult. For example action filters.
But in terms of the actual unit test it doesn't change anything:
you create a mock to represent some object that the subject under test depends upon and that you can control in your unit test
you define expectations on the mocked object
you call the actual method you are testing
you assert on the results

Easily mockable HTTP client framework for C#

In a upcoming project I'm going to write an application in C# which partly has to communicate with a HTTP server. I'm very fond of writing my code TDD-style, and I would just love it if I could mock all of the HTTP requests in my tests.
Does any one here know about an easly mockable HTTP client framework?
Ps. I usually use Moq for mocks. If you know of some free mocking framework that would be better to mock HTTP requests, that would be nice too.
DotNetOpenId, an open source project from which you may reuse code, uses HTTP wrapper classes through which all calls are made. During testing, a mock HTTP handler is injected so that the responses can be programmatically set before the call is made. It has another mode where it hosts its own ASP.NET site so that the full actual stack can be exercised.
This works well, although it hasn't been pulled out as a standalone solution. If you're interested in reusing it, here are some relevant links to the source. And you can ask for help integrating it at dotnetopenid#googlegroups.com.
Live one:
StandardWebRequestHandler.cs
Mocks: MockHttpRequest.cs, TestWebRequestHandler.cs
I suggest you use the framework support for this i.e. System.Net.WebRequest.
Define a really simple interface, and a simple wrapper for the webrequest. This way you will get what you want, and won't add an external dependency for something the framework already does well.
You could use WireMock.Net which is a flexible library for stubbing and mocking web HTTP responses using requests matching criteria.
And this can also be used very easily in unit -test projects. Check the wiki for details.
NuGet is found here.
I don't think there is actually any framework which handles the things you want to archive. After all only you know what each Http request should do. So basically you have 2 options:
Making the calls and using a dummy implementation on the other side. This may be a simple console application which returns dummy data. If you need more logic I would consider using an object database - in my opinion they fit perfectly for these applications.
Use a mock- implementation on the application side. If this implementation has much logic don't use any mocking framework - create a custom mock class which has all the logic.
Hope this helps

Categories

Resources