Entity Framework Core makes it easy to write tests that execute against an in-memory store but sometimes we want to actually run our tests against a real relational database. In this episode, Monster Dave looks at how to create an integration test that runs against a real SQL Server database.
Announcing the Microsoft Press “ASP.NET Core Application Development” Book from the ASP.NET Monsters
Working through the authors’ carefully designed sprints, you’ll start with a blank canvas, move through software architecture and design, adjusting to user feedback, recovering from mistakes, builds, testing, deployment, maintenance, refactoring, and more. Along the way, you’ll learn techniques for delivering state-of-the-art software to users more rapidly and repeatably than ever before.
I can’t remember if NodeJS is still cool or if people are only using it ironically now as they port their applications to something else. In either case there are still a lot of great node modules out there which it would be great to access from our ASP.NET application. In this episode we’ll look at Node Services an approach to call out to Node from inside an ASP.NET MVC Core controller.
Entity Framework Core makes it easy to write tests that execute against an in-memory store. Using an in-memory store is convenient since we don’t need to worry about setting up a relational database. It also ensures our unit tests run quickly so we aren’t left waiting hours for a large test suite to complete.
While Entity Framework Core’s in-memory store works great for many scenarios, there are some situations where it might be better to run our tests against a real relational database. Some examples include when loading entities using raw SQL or when using SQL Server specific features that can not be tested using the in-memory provider. In this case, the tests would be considered an integration test since we are no longer testing our Entity Framework context in isolation. We are testing how it will work in the real world when connected to SQL Server.
For this example, I used the following simple model and DbContext classes.
In an ASP.NET Core application, the context is configured to use SQL Server in the
DefaultConnection is defined in
appsettings.json which is loaded at startup.
MonsterContext is also configured to use Migrations which were initialized using the
dotnet ef migrations add InitialCreate command. For more on Entity Framework Migrations, see the official tutorial.
As a simple example, I created a query class that loads scary monsters from the database using a SQL query instead of querying the
To be clear, a better way to write this query is
_context.Monster.Where(m => m.IsScary == true), but I wanted a simple example. I also wanted to use
FromSql because it is inherently difficult to unit test. The
FromSql method doesn’t work with the in-memory provider since it requires a relational database. It is also an extension method which means we can’t simply mock the context using a tool like
Moq. We could of course create a wrapper service that calls the
FromSql extension method and mock that service but this only shifts the problem. The wrapper approach would allow us to ensure that
FromSql is called in the way we expect it to be called but it would not be able to ensure that the query will actually run successfully and return the expected results.
An integration test is a good option here since it will ensure that the query runs exactly as expected against a real SQL Server database.
I used xunit as the test framework in this example. In the constructor, which is the setup method for any tests in the class, I configure an instance of the
MonsterContext connecting to a localdb instance using a database name containing a random guid. Using a guid in the database name ensures the database is unique for this test. Uniqueness is important when running tests in parallel because it ensures these tests won’t impact any other tests that aer currently running. After creating the context, a call to
_context.Database.Migrate() creates a new database and applies any Entity Framework migrations that are defined for the
The actual test itself happens in the
QueryMonstersFromSqlTest method. I start by adding some sample data to the database. Next, I create and execute the
ScaryMonstersQuery using the context that was created in the setup method. Finally, I verify the results, ensuring that the expected data is returned from the query.
The last step is the
Dispose method which in xunit is the teardown for any tests in this class. We don’t want all these test databases hanging around forever so this is the place to delete the database that was created in the setup method. The database is deleted by calling
These tests are slow! The very simple example above takes 13 seconds to run on my laptop. My advice here is to use this sparingly and only when it really adds value for your project. If you end up with a large number of these integration tests, I would consider splitting the integration tests into a separate test suite and potentially running them on a different schedule than my unit test suite (e.g. Nightly instead of every commit).
You can browse or download the source on GitHub.
Earlier in November, the ASP.NET Monsters had the opportunity to take part in the ASP.NET Core hackathon at the Microsoft MVP Summit. In past years, we have used the hackathon as an opportunity to spend some time working on GenFu. This year, we wanted to try something a little different.
A few months ago, we had Taylor Mullen on The Monsters Weekly to chat about Razor in ASP.NET Core. At some point during that interview, it was pointed that MVC is designed in a way that a new view engine could easily be plugged into the framework. It was also noted that implementing a view engine is a really big job. This got us to thinking…what if we could find an existing view engine of some sort. How easy would it be to get actually put a new view engine in MVC?
And so, that was our goal for the hackathon. Find a way to replace Razor with an alternate view engine in a single day of hacking.
We wanted to pick something that in no way resembled Razor. Simon suggested Pug (previously known as Jade), a popular view template engine used in Express. In terms of syntax, Pug is about as different from Razor as it possibly could be. Pug uses whitespace to indicate nesting of elements and does away with angle brackets all together. For example, the following template:
would generate this HTML:
To our surpise, this not only worked, it was also easy! We created a very simple file called pugcompile.js.
model is the view model we want to bind to the template and
mytemplate.pug is the name of the file containing the pug template:
Now that we had proven this was possible, it was time to integrate this with MVC by creating a new MVC View Engine.
We decided to call our view engine Pugzor which is a combination of Pug and Razor. Of course, this doesn’t really make much sense since our view engine really has nothing to do with Razor but naming is hard and we thought we were being funny.
Keeping in mind our goal of implenting a view engine in a single day, we wanted to do this with the simplest way possible. After spending some time digging through the source code for MVC, we determined that we needed to implement the
IViewEngine interface as well as implement a custom
IViewEngine is responsible for locating a view based on a
ActionContext and a
ViewName. When a controller returns a
View, it is the
FindView method that is responsible for finding a view based on some convetions. The
FindView method returns a
ViewEngineResult which is a simple class containing a
boolean Success property indicating whether or not a view was found and an
IView View property containing the view if it was found.
We decided to use the same view location conventions as Razor. That is, a view is located in
Here is a simplified version of the FindView method for the
You can view the complete implentation on GitHub.
Next, we created a class called
PugzorView which implements
PugzorView takes in a path to a pug template and an instance of
INodeServices. The MVC framework calls the
RenderAsync when it is wants the view to be rendered. In this method, we call out to
pugcompile and then write the resulting HTML out to the view context.
The only thing left was to configure MVC to use our new view engine. At first, we thought we could easy add a new view engine using the
AddViewOptions extension method when adding MVC to the service collection.
This is where we got stuck. We can’t add a concrete instance of the
PugzorViewEngine to the
ViewEngines collection in the
Startup.ConfigureServices method because the view engine needs to take part in dependency injection. The
PugzorViewEngine has a dependency on
INodeServices and we want that to be injected by ASP.NET Core’s dependency injection framework. Luckily, the all knowning Razor master Taylor Mullen was on hand to show us the right way to register our view engine.
The recommended approach for adding a view engine to MVC is to create a custom setup class that implements
IConfigureOptions<MvcViewOptions>. The setup class takes in an instance of our
IPugzorViewEngine via constructor injection. In the configure method, that view engine is added to the list of view engines in the
Now all we need to do is register the setup class and view engine the
Like magic, we now have a working view engine. Here’s a simple example:
So we reached our goal of creating an alternate view engine for MVC in a single day. We had some time left so we thought we would try to take this one step further and create a NuGet package. There were some challenges here, specifically related to including the required node modules in the NuGet package. Simon is planning to write a separate blog post on that topic.
You can give it a try yourself. Add a reference to the
pugzor.core NuGet package then call
.AddMvc() in the
Razor still works as the default but if no Razor view is found, the MVC framework will try using the PugzorViewEngine. If a matching pug template is found, that template will be rendered.
We had a blast working on this project. While this started out as a silly excercise, we sort of ended up with something that could be useful. We were really surprised at how easy it was to create a new view engine for MVC. We don’t expect that Pugzor will be wildly popular but since it works we thought we would put it out there and see what people think.
We have some open issues and some ideas for how to extend the
PugzorViewEngine. Let us know what you think or jump in and contribute some code. We accept pull requests :-)
ASP.NET Core 1.1, .NET Core 1.1, EF Core 1.1 and a multitude of other packages have all been released, but is now the time to adopt?
In this episode Monsters Dave and James talk about the release of ASP.NET 1.1 and how it will affect your projects. They mash on the tooling, upgrading a package and their experiences so far and hint at a few topics that are coming in future episodes.
For additional details on the release, be sure to check out these links:
- The ASP.NET Core 1.1 announcement
- The .NET Core 1.1 announcement
- The change manifest with all the updated packages
Please follow the @aspnetmonsters, like and share, or comment and ask questions below.
If you’re looking for content that will walk you through, step-by-step, as you transition to ASP.NET Core MVC, you’re in for a treat.
In this episode of the Monsters, Jon Gallaway joins us live on set at Channel 9 studios to talk about the .NET Core community, the Community Standups and, of course, a series of free labs that you can dive into to embrace your inner Core and learn more about the future of MVC.
Check out the labs yourself on GitHub:
Please follow the @aspnetmonsters, like and share, or comment and ask questions below.
Azure Functions have just gone "GA" and are a great way for you to truly leverage the promise of the cloud and it’s ability to scale. In this episode of the Monsters, we have a special guest from the Functions team to break down some of the basics and help us wrap our heads around the Azure offering.
Join Chris Anderson and the ASP.NET Monsters at the Channel 9 studios as they chat about Azure Functions.
Check out these links:
- Monster James chews on Azure Functions for 5 days in this series
- See the C# developer reference for Azure Functions