Using ASP.NET Core TestServer + EF Core In Memory DB Together

I haven’t seen much about using the ASP.NET Core TestServer and EF Core’s InMemoryDb together, despite them being a natural fit, so I thought I’d blog about it.  There are a few different ways you could achieve this (more options at the bottom of the post), this is just a simple solution.

 

tldr;

  1. Create a custom environment called Testing.
  2. In your Startup.cs, add a check to see if you’re in the Testing Environment and if so use the InMemoryDb provider.
  3. In your TestServer setup, set the environment to Testing.
  4. Grab the DbContext from TestServer via server.Host.Services.GetService(typeof(ApplicationDbContext)) as ApplicationDbContext and add the data you want there.
  5. You now have an in memory web server and an in memory database working together!

Full Code here on GitHub

Quick look at final Test class:

 

 

Test Server

Unit tests test a small piece of the raw logic of your code in isolation of any web server, database, file system, etc.  Instead of using a real database, you would use a fake or mock database.

Integration tests on the other hand, are a way of doing automated tests that integrate various components of your app together.  It might use a combination of a real web server, real web service, real database, real browser, etc.  ASP.NET Core gives us an easy way to write integration tests by way of an object called TestServer.

TestServer allows you to boot up an in memory web server with your full middleware pipeline, full set of dependencies registered, etc.  This enables you to do things like hit a route and make sure the server returns the response you expect.

For more information on Test Server, checkout the official docs.

 

EF Core InMemory Database

EF Core has a provider that lets you run against an in memory database.  The intent of this provider is purely for testing purposes. 

This has a few benefits:

  1. The reads and writes are very fast.
  2. You don’t have to worry about having a real database to run your tests against.
  3. You don’t have to worry about cleaning up your data after your tests are done.  When the tests stop, your in memory database goes away.

For more information on InMemory database, checkout the official docs.

 

Using these two together

By now you may be thinking.  “Cool, so I can create an in memory web server and an in memory EF database…. can I combine the two?”  The answer is most definitely, yes!  I hadn’t seen much out on the Interwebs about this, so hence this blog post.

Let’s assume we have an API endpoint that looks like this:

 

It’s pretty straight forward, we inject in a DbContext into the Controller (NOTE: DEMO CODE) and then have an endpoint that takes in an ID and will return the appropriate response based on what the database returns.

So what I’d like to do is swap out the real database here for the in memory database.  Let’s do it!

 

First in your ASP.NET Core Application:

  1. In our Startup.cs, let’s inject an IHostingEnvironment in the constructor and save it to a field/property.
  2. In ourConfigureServices, let’s check the Environment to see if the current environment is a custom one called “Testing.”
  3. If so, then rig up the In Memory Database via services.AddDbContext<ApplicationDbContext>(options => options.UseInMemoryDatabase("TestingDB"));
  4. Note: TestingDB is just a unique name given to your In Memory Database.
  5. So it should look like:

 

Next in your Unit Testing project (I’m using xUnit, but you could use NUnit or MSTest):

1.Create a new Test Class

a. I follow the convention <ClassUnderTest><MethodUnderTest> for the class name.

b. In this case: ApplicationUsersControllerGetApplicationUser

2. Create a new constructor and set up a WebHostBuilder with the following code.  The two biggest pieces are line 9 where we set the Environment to Testing (to match line 14 above where we check the Environment), and line 13 where we grab the ApplicationDbContext from the ServiceProvider and save that off.

3. Create a new test method

a. I follow the convention Does<Something>_Given<Scenario>.

b. In this case: DoesReturnOk_GivenUserExists

4. Create a user, add it to the context, and save it.  Then use the HttpClient we created and saved off above to query our endpoint and ask for the user’s ID.

 

That’s it!  Now run your test and you will have successfully booted an in memory web server with an in memory database.

 

Now that we’ve tested the Ok path, we should probably test the NotFound path.  That’s simple to do as well:

The entire GitHub code can be found here: https://github.com/scottsauber/TestServerAndInMemoryDbDemo.  The two interesting parts are the Startup and the Tests.

 

Some “Before You Copy + Paste” Caveats

  1. If you don’t like polluting your “Production” Startup class with Testing concerns (which is a very valid concern), you could create a Test only Startup class.   has a great blog post on how to do this near the bottom of his post.  On your TestServer then just swap out .UseStartup<Startup>() with .UseStartup<YourTestStartupClassHere>().
  2. In no way am I advocating for injecting in your DbContext directly into your Controller.  This is purely just demo code and to remove layers to make it as easy to reason about as possible.  Likely you will have at least one “layer” in between your Controller and your DbContext.
  3. Note that this will be doing a real integration test and I am ONLY swapping out the DB here.  If you need to swap out other components (like external services), you will also have to do that yourself via the
  4. You will want to limit your creation of the TestServer and HttpClient, due to they are mildly expensive (~100-200ms on my machine), and we want our tests to be as fast as possible.  If using xUnit, look into IClassFixtures.

 

Hope this helps!

Customizing EF Core 2.0+ Entity/Table Mapping with IEntityTypeConfiguration

tldr;

In EF Core 2.0, you can now rip out your per-Entity Fluent API table customizations into separate classes instead of having them all in the OnModelCreating method of your DbContext.  You do this by inheriting from IEntityTypeConfiguration<T>.

 

Before In EF Core 1.x, note lines 13-33:

 

After in EF Core 2.0+, note lines 13, 14, and the 2 extra files:

 

The latter scales better to a big application with lots of entities.

 

The Problem

Let’s say you want to make a customization to one of your EF Core 2.0 properties and how it maps to your underlying database.  Some customization scenarios include changing the default table name, changing the max length of the column, etc.

 

There are two ways of doing this.  You could either choose the Data Annotations way or using the Fluent API.  I personally like the Fluent API, so that my models aren’t littered with attributes.  It also decouples my models from Entity Framework, in case I choose to use Dapper or another ORM down the road.

 

Prior to EF Core 2.0, to use the Fluent API you would have to “inline” any customizations in your OnModelCreating method.  This works ok for small projects, but as you add tons of tables to your DbContext, this becomes a little hard to manage.

 

This would look something like this:

It looks ugly just for two tables… imagine 10, 20, or even 100!  …Although maybe you should have multiple DbContexts at that point, but that’s beside the point.

 

This obviously doesn’t scale great.  You could rip out each configuration into your own custom classes or static methods, but now there is a built-in solution in EF Core 2.0+.

 

The Solution

With EF Core 2.0 and above, you can now implement the interface IEntityTypeConfiguration<T> where T is the Model you’re configuring.  After creating that class with the necessary customizations, you need to wire that up to your DbContext’s OnModelCreating method by calling builder.ApplyConfiguration(new ConfigClass).  It’s important to make sure that your customizations come after the base.OnModelCreating(builder) call.

 

It looks something like this, note lines 13, 14, and the two extra files:

 

That looks much better and scales much nicer.

If you use the “inline” way today, you should be able to convert to the IEntityTypeConfiguration way without impacting the rest of your app or changing any schema.  The API is the exact same in both formats (i.e. it’s HasKey in both spots to change the Primary Key).

 

Reverse Engineering from Existing Database

While you could handle your customization in EF Core 1 via custom static methods or your own hand rolled classes for maintainability purposes, now we have a consistent way of doing this across all EF Core Projects.  That enables awesome things.

Such as the EF team is starting to work on adding this as an option when you Reverse Engineer classes from an existing database and have it auto-generate your customizations for you into these separate IEntityTypeConfiguration<T> classes.  It’s currently slated for the EF Core 2.1 release that is likely to be released late this year or early next year.  Obviously no guarantees that EF Core 2.1 lands at that time or that it includes this feature.  However, it’s awesome that this is coming down the pipe.

 

This is also possible in EF 6

One final thing I’d like to mention is that you could do this same thing in EF 6.  You just have to inherit from the EntityTypeConfiguration<T> abstract class (not an interface like EF Core), and then put your configuration in the constructor.  There are many examples out there on how to do that and is outside of the scope of this post, but just thought I’d pass along in case you like this pattern and are using EF 6 today.

 

Hope this helps!

Fixing ASP.NET Core Feature Folders Causing Resharper Intellisense Issues

I’ve had a handful of people ask me about this, so I figured I’d just blog on it.

The Problem

If you use Feature Folders in ASP.NET Core you may see something like this where Resharper can’t figure out where your Views are.  It will outline your View() calls in red (as well as your partials).

2017-08-24_22-57-12

 

When you run the app it still works, but it leaves a little to be desired with the Developer experience.  Feature Folders are supported in Resharper and plain ASP.NET, but in ASP.NET Core Resharper has not added support for Feature Folders yet.

 

The Fix

Luckily, there’s a workaround, that I was first notified of by Bill Sorensen on my blog post on Feature Folders linked above.

1. Install the JetBrains.Annotations NuGet package

2. Add the following attributes to the top of your IViewLocationExpander file, above the namespace*

3. Re-open your Controller and everything should work

 

  • Note – if you have more custom paths in your IViewLocationExpander than just those, then you’ll have to add those routes as well.

 

So your final output should look something like this:

 

That’s it, now Resharper is happy!

 

2017-08-24_23-11-51

 

Hope this helps.