Asserting Open API Documentation For ASP.NET Core [xUnit]
June 6, 2023
• 391 views
C# tutorialC# programminglearn c#c# programmingc# tutorialasp.net coreasp.net core tutorialasp.net core minimal apiasp.net core minimal web apiasp.net core web api tutorialasp.net tutorialasp.net core beginner tutorialasp.net core beginnersasp.net core for absolute beginnersasp.net core get all routesasp.net core test routeswaggeropen APIminimal apiclean architecture.net 7 web apidotnet 8dependency injection in asp.net core
In this video, we'll look at how we can write functional tests in xUnit to assert that our routes that we have registered in our ASP.NET Core application have XML documentation comments enforced. These XML documentation comments get translated by Swagger into Open API style documentation, so as long as we can enforce proper XML comments, we're ready to rock!
For more videos on programming with detailed examples, check this out:
https://www.youtube.com/playlist?list=PLzATctVhnsghN6XlmOvRzwh4JSpk...
View Transcript
hey thanks for checking out this video today we're going to be looking at writing some functional tests for an asp.net core application and a particular building on an example from last time where we were investigating some of the properties on the routes of our asp.net application and what I wanted to do is build on that and go to API documentation so in particular looking at the dot comments that we get exported from our methods and then writing tests that can check to make sure that our DOT comments are aligned with our routes and the reason that this is interesting for me is because if I want to publish my API I want to make sure that I have a good set of documentation for users to go along with it and with that said let's jump over to visual studio and get right into it
alright here in Visual Studio I just have some of my functional tests for my routes so I am going to be using X unit for this example but the concepts we're going to be talking about should apply to any testing framework I just wanted to call it out so that when you see things like trait or when I go down a little bit lower you'll see fact these are just X unit concepts for setting up our tests but they're not really necessary for you to understand as we walk through this in my previous video I was demonstrating that I have all of this Builder pattern to be able to set up an API instance and then have a client connect to that instance of the server so that I can go run some tests against it for this discussion we don't actually need a client
to be able to make calls to the web server but when we do start up the web server we do want to be able to hook into it and I talked about this in the last set of videos and that's because we need to be able to query from the application what our available routes are I'm just going to jump into this class right here ensure HTTP method attributes because in my previous videos I was showing that these classes that are registered like this are going to get called on Startup for my application so if I press F12 and jump over to that right now we can go see that this is going to be the code that's going to be run on Startup so in particular as I demonstrated in the previous videos we're just going to be calling this web application Services property
to be able to get these endpoint data source Services I'm going to get the entire collection of all of the endpoints we're doing a select many to get all of the endpoints so this just creates a list of all of the registered routes for our application and I am going to be skipping over the signalr stuff because I am just interested in HTTP methods right now in particular just get and post so if I scroll down a little bit lower you'll see that I actually explicitly look for just a single instance of one of these attributes get or post I don't have put delete or other things on my methods right now so if I did want to extend this test to be able to support that kind of thing I'd just be able to add this next we're going to be grabbing the actual
method right off of this method info which is going to be an attribute on our route so just leveraging some reflection we're able to get that method info and that method info is going to be quite literally the method that's called when our route is hid so if I scroll down a little bit lower we're going to look at some potential magic that's going on here this is a little bit nasty but just in order to clean up this method name to be able to get a full method name including the actual type and the namespace all that I'm doing is basically formatting this string to be the full name space and then the method name and the reason that I'm doing that is because I want to go look that up inside of the XML document that's output when we have our DOT comments
so to explain explain that a little bit further I'm just going to jump over to one of my files that has some routes and look at that briefly this files an example of my food routes from my application that I'm currently working on and you can see that it has this documentation comment style triple comment that's actually a common thing that you'll see inside of a lot of applications generally for my own internal usage I don't really leave comments and stuff like this because I try to make my own methods self-describing however because this is going to be an API that I do want to make public I do want to be able to offer documentation for the apis that I have available I figured if I can leverage the documentation inside of the code with this triple comment style and then output that documentation
when the project is built which is really just a property of the project itself which we can see right here inside of the Cs proj file where we have this generate documentation file to true and as a result of leaving comments like this and having that flag set to true when I go go to build my actual project I will get an XML documentation file output with it now leveraging Swagger and open API we're able to actually have this documentation automatically translated into Swagger documentation and this way when I combine what I have in the code I automatically just get Swagger open API documentation created for me now this brings us back to our test here and because I was explaining that I wanted to format the full method name the next part of our test that we want to be able to do is
actually open up the XML document so we're going to format the path to actually get where this XML documentation is going to exist and you'll see that I'm actually asking the method for the module and then its assembly and its location so what's really neat about this is that if I call this code right here this get file name without extension is going to give me the name of the dll without dot dll on it and then I can replace that with DOT XML instead and because I know that's going to be in my output directory when I build this entire thing is going to give me the path to my XML documentation and like I said that XML documentation is going to translate right into our open API documentation so at this point I have a reference to our XML documentation and I also
know what route that I'm looking at so the next thing that we can do is actually load up this XML document right here on lines 120 and 121 and then I'm going to use something called XPath and there's lots of resources online that explain what XPath is but essentially it's a style of lookup that allows you to go look up structured node information inside of things like XML and there's something similar for Json as well but using this syntax I'm actually able to go go look up the full method name XML attribute so if we look at lines 123 through 126 this is actually going to go find us that documentation node specifically for our method scrolling a little bit lower we can say that if we don't have a documentation node all that we're going to do is fail this test immediately and indicate
to the person running the test that we must have XML documentation for every route that we have available now building on this if I wanted to go extend this concept to not just pass or fail depending on whether or not documentation is present I could actually start looking inside of the documentation and trying to assert that if I have things like authentication or I have things like that I need to post particular types of Json that I can actually look at the route information and compare it with the documentation to make sure that something is included there now because my project is still in the early phases I don't actually have a standard that I want to adhere to however if I jump back over to the routes and we have a quick look at some of the other attributes that are on here for
example I might want to be able to say that if I have this produces response type status code and say that I have this list of 200 400 and then some of the other ones up to 415 here perhaps I want to ensure that I have these responses also included in the XML documentation currently I don't have that but that's a simple example of something that I might want to do so that I can actually ensure that there's no extra response XML documentation nodes and inversely that I don't have missing ones for the ones that are listed here on these attributes another quick example is that if I have rate limiting perhaps I want to include in the XML documentation for each route that I have particular types of rate limiting and this just says default on it but maybe that means that at some
point if I have something that says enable rate limiting default that maybe something like in the remarks I need to have something like rate limiting is enforced and then some information about what that rate limiting actually is and if I go back to our tests that means that if I was able to look up one of the attributes on that route so scrolling back up here if I was able to actually ask out of this list of attributes for something about the rate limiting I could go check to make sure that this XML documentation node that we have right here on line 123 actually has some standardized text about the rate limiting all right that's just a quick example for today about how I'm trying to build some functional tests to enforce that I have XML documentation on my roads so that when I go
to publish my routes I have some Swagger API docs that are perfectly aligned with my routes in my API the current version of this that we're looking at is really just to ensure that there is some documentation for any route that I have available and in particular I'm just looking at get in post for now so this is just the basis for building out these tests for documentation but as I try to build up my standards a little bit more I can try to write tests that actually ensure that I have standardized documentation depending on what routes and what attributes those routes have thanks so much for watching I hope you found this useful and we'll see you next time
Frequently Asked Questions
What is the purpose of writing functional tests for an ASP.NET Core application?
The purpose of writing functional tests for an ASP.NET Core application is to ensure that the API documentation aligns with the routes defined in the application. This helps in maintaining a good set of documentation for users when publishing the API.
How do I generate XML documentation from my ASP.NET Core project?
To generate XML documentation from your ASP.NET Core project, you need to set the 'Generate Documentation File' property to true in your .csproj file. This will output an XML documentation file when you build your project.
What testing framework do you use in this video, and can I use a different one?
These FAQs were generated by AI from the video transcript.In this video, I use xUnit as the testing framework. However, the concepts I discuss are applicable to any testing framework, so you can use whichever one you prefer.
