XUnit – MemberDataAttribute and generic type inheritance

1. Introduction.

When I was writing Cake.Intellisense I was playing a lot with Roslyn syntax rewriters. The one thing which was pretty important for me at this time was a reliable set of tests which can quickly show if rewritten code is valid C# code and if it matches my expectations. As I don’t like to repeat my code I wanted to have a base test class which can be provided with different test cases from inherited classes. The initial implementation looked as follows

As you can see I have a generic base test class which holds test cases in a static field TestCases. The field is static as it is required by XUnit, this solution is perfectly valid because a static field is shared across all instances of the same type. Having a base test class ready I wanted to write a set of unit tests for following syntax rewriter

The rewriter shown above is a very simple piece of code which replaces internal class modifier with a public one. Writing the tests for that class was supposed to be very easy, I just had to provide test cases with input code and expected result.

Unfortunately running the tests resulted in InvalidOperationException being thrown from XUnit

If you look closely at the message you will notice that the TestCases field used for providing data was not initialized, which means that the static constructor of class InternalToPublicClassModifierSyntaxRewriterTests was not run. That was pretty surprising for me that is why I wanted to investigated the issue a bit more.

2. Investigation.

I started from going back to the basics. As we probably all know, the static constructor is triggered when one of the following events occur:

  • An instance of the class type is created.
  • Any of the static members of the class type are referenced

The first condition is not met because instance of the test class is created after test cases are enumerated. That is why member data fields have to be a static fields/properties etc. When it comes to second condition the situation in here is a bit more complicated but if you take a look at the MemberDataAttributeBase class

you will notice that member data looks for properties in DeclaringType of method. In my case declaring type is

not

So when XUnit accesses TestCase property the static constructor from InternalToPublicClassModifierSyntaxRewriterTests class will not be called either as the types does not match.

3. Solution.

In order to bend the behavior of XUnit to my needs, I had to ensure that the static constructor from inherited class is called. Fortunately, workaround is pretty straightforward – I had to introduce a custom MemberDataAttribute which calls static constructor from ReflectedType manually

Now all I have to do is use newly created attribute in CSharpSyntaxRewriterTest test class

From now on all of the test cases will be run correctly

Source code for this post can be found here

XUnit – MemberDataAttribute and generic type inheritance

NSubstitute – returning value from IEnumerable

I’ve been using NSubstitute combined with automocks for quite some time already, but recently I’ve encountered quite interesting situation. Let’s assume that we have the following class we need to write tests for

As mentioned before I wanted to test that class leveraging the concept of automocks. If you have never used them before, no worries, the idea is pretty simple. Instead of providing mock dependencies manually, you just generate them automatically. Once the dependencies are mocked you can retrieve and set them up if necessary. So in my case, I have to setup IEnumerable<IValidator<Price>> mock so that it yields some values. It can be achieved by mocking return values of GetEnumerator() method.

The entire test then can be written as

Everything looks good at that point, however if you run the tests, it will fail
FailedTest
That was quite surprising for me and I have to admit that at the beginning I thought it was a bug in NSubstitute.
However, if you looks closely at the implementation of the test, you will see that every time validator collection is enumerated, the same instance of the enumerator is used. As the enumerator keeps its state, the first enumeration (_innerValidators.Any()) will move a current element to the first position (which is the last position at the same time) so when I try to enumerate again (_innerValidators.All(validator => validator.IsValid(input)) enumeration will continue from the previous position and the iteration will end yielding no results. Fortunately, with NSubstitute you can configure the call so that it always returns a new value. The relevant code changes are shown below

Running the tests again will give us “green” result
Green

Source code for this post can be found here

NSubstitute – returning value from IEnumerable

Dotnet CLI – running tests from multiple assemblies

When you start looking for information how to run unit tests for .NET Core based projects in the command line, you will most probably stumble upon dotnet CLI and its dotnet test command.
The command works really great when you have just one test project in your solution, however, it doesn’t allow you to run tests from multiple projects at once. Of course, you can write little PowerShell which will run the command in the loop e.g.

Unfortunately, in this case, you won’t get an aggregated summary of tests results, instead, you will get a summary per test project.
dotnettest
Luckily dotnet CLI have another command for running tests – namely dotnet vstest. In this case, we do not operate on projects but we provide a location for assemblies with tests. So if you, for instance, would like to run unit and integration tests at once, you can write something like that

If you want a bit more flexible solution this simple PowerShell script will scan files and based on naming convention retrieve tests assemblies.

One way or another, the dotnet vstest command will aggregate all of the test results and will present them as one summary.
dotnetvstest
One thing to note, dotnet vstest won’t build the solution, you have to run the build manually with dotnet build command.
Source code for this post can be found here

Dotnet CLI – running tests from multiple assemblies

ASP.NET Core – API versioning by convention

1. Introduction

If you were looking for information about API versioning support for ASP.NET Core you’ve probably come across Microsoft.AspNetCore.Mvc.Versioning library. The library itself allows you to set up versioning in a couple of different ways, for instance, via attributes or via manual convention setup. All of this options are really nice but unfortunately, they have one significant drawback, namely, you have to set them up manually. As I tend to forget about this kind of things I wanted to automate that process as much as possible. Thankfully ASP.NET Core has a very nice feature called ApplicationModelConventions which allows you to add some metadata(like routing information, API versioning ) to your controller, actions etc.

2. Convention

I’ve decided to implement versioning by routing which means the API will be accessible via this template

The template itself doesn’t give you much, as you also have to add information to the controllers which version of API they support. In my case, I decided to go with a version by namespace convention, which means that supported version will be deduced from namespace in which given controller resides. So, in fact, there will be two conventions, one for applying routing and a second one for applying versioning

3. Creating conventions.

In order to write an ASP.NET Core convention, we have to implement IApplicationModelConvention interface. This interface has a single method Apply which takes ApplicationModel class as an argument. This class gives us access to all of our controllers, actions and other parts of the application. So if we want to apply a routing with versioning for all of the controllers, we can do it in following way

As you can see we iterate through all of the Selectors and then apply new route model to them. If selector already had a route attribute applied we combine two attributes together. Once our convention is applied our actions will be accessible with following routing prefix

or via

Having our routing ready now it is time to add versioning information to our controllers. Once again it will be done via application model convention. The version of the controller will be deduced from the namespace given controller is located in.

As you can see I iterate through all of the controller models of our application, then check the version of controller based on its namespace and finally with

I am able to inform the framework which version of API given controller supports.

4. Adding convention to application

Having all of our conventions prepared now we can enable versioning support

And of course, we have to add newly created conventions to list of application conventions

Note that I removed ApiVersionConvention and ImplicitControllerVersionConvention with simple extension method Remove<T>

to make sure that only my convention is responsible for API versioning.

Source code for this post can be found here

ASP.NET Core – API versioning by convention

ASP.NET Core – default API version with url path versioning

1. Introduction.

When you start versioning your API sometimes you want to have access to your endpoints without specifying version explicitly. Thanks to Microsoft.AspNetCore.Mvc.Versioning library this can be easily achieved with proper setup of configuration action. However, it turns out that in order to enable default API version for url path versioning, there are a couple additional steps to do.

2. Default API version without url path versioning

Let’s start with the initial setup of API versioning which will work for every type of versioning apart from url path versioning. All you have to do is to assign an ApiVersionSelector and set the AssumeDefaultVersionWhenUnspecified property to true.

Now when the user will try to access the endpoint without specifying version explicitly the ApiVersionSelector will select proper version – in this case highest available version.

3. Default Api version with URL path versioning

Running the same configuration against controllers which are versioned via url path (not query string)

will result with 404 status code, as routing is not able to match the url.
404
Fortunately, unlike the ASP.NET Web API, ASP.NET Core allows us to have multiple route attributes applied to given controller, so in order to fix the issue we just have to add

attribute to versioned controllers. From now on we can access our API without specifying version as well as with version specified.
after

4. Adding default route with convention

If you don’t want to specify default route manually for every controller, you can do it via application model convention. The interesting thing about it is the fact that apart from changing existing values of application model we can also add new items to it. This means that we can add additional SelectorModel with our default route to Selectors’ collection

Now we can get rid of [Route(“[controller]”)] attribute from our versioned controllers and just rely on convention which can be added as follows

Source code for this post can be found here

ASP.NET Core – default API version with url path versioning