.net core tutorials

Entity Framework Core In Memory Testing database

Entity Framework core has really simplified working with databases and has drastically improved the testability aspects of these databases. Providing developers the ability to create their databases as seperate class library projects.

As any developer will tell you releasing a product or library without testing it is generally accepted as an unforgivable sin in the software development world. Therefore if you’re making use of the Code-First database development process, enabled via Entity Framework then you should also ensure you at least make an attempt to write Unit & Integration tests for your databases.

Code available on Github

 

What are Unit tests

Unit tests are used to check if small units of code are functioning as you would expect them to. Typically this testing is done as part of the development process, and a unit test will check that the code being tested meets a specification, while a library of unit tests together will check the functions expected of the application. The process is usually automated, which allows the library of tests to be re-run frequently, allowing us to find bugs earlier, and in smaller units of code, which are easier to debug.

A unit test is an automateed piece of code that invokes the method or class being tested and then checks some assumptions about the logical behaviour of that method or class.

Unit Tests enable developers to think and reason about their code in a modular fashion. They are frequently combined with a continuous integration system, to regression test changes, and help speed up and minimize the risk from refactoring.

Unit testing can also form the basis of documentation – as the functional requirements should tie to unit tests, and vice versa, allowing you to see which requirements are met by the developed code.

My two favourtie books on Unit Testing : The Art of Unit Testing: with examples in C# by Osherove, Roy (2013) Paperback & Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin) explain how Unit testing, done right, can be the difference between a failed project and a successful one, between a maintainable code base or a big ball of mud.



Using In Memory Databases in Unit tests

When developing Unit or Integration Tests you don’t want to use a physical database on a server, because you don’t necessarily want to concern yourself with ceremony or administration tasks of maintaining the database server. Fortunately Entity Framework core provides a couple of different in-memory database options to assist in developing tests.

These two choices for in-memory database providers depend on whether or not you’re using the Microsoft.EntityFrameworkCore.Relational package and if you need the full behaviour of a relational database during testing i.e. Foreign Key Constraints etc.

If you don’t really want to or need to worry about Relational database characteristics then you can make use of the Microsoft.EntityFrameworkCore.InMemory or if you would prefer a simulation closer to the real thing then Microsoft.EntityFrameworkCore.Sqlite should be your library of choice.

In order to provide examples of using both these options I will use the unit tests of my Generic Repository Nuget Package .

Can’t wait to see it in action ?

Check out the code on GitHub

Code

All code in the examples make use of my current favourite Unit Testing Framework xUnit, but should be fairly easy to convert to any of the others.



Testing Entity Framework Core using In-Memory Database Provider

To use the In-Memory database provider first we need to add the following nuget package :

In order to create an instance of a DbContext to use for our tests, we create an instance of DbContextOptions. To create an instance of DbContextOptions use the DbContextOptionsBuilder class.

A key point to take note of is that we generate a GUID to use as a name for the database. This is to ensure that every TestContext run has new database that is not affected by other test runs.

View Full Code

Although not completely necessary I make use of Class Fixtures to share contexts between tests.

 



Testing Entity Framework Core Relational Databases using SQLite In-Memory Mode

The SQLite provider itself is a relational database provider, However we can take advantage of SQLite in-memory mode. The key benefit is that we get the full behavior of a relational database, with the benefits of the running in-memory.

By default each SQLite connection using the ":memory:" connection string will use a different in-memory database, so we don’t need to generate a new name for each connection.

An Additional step required for the SQLite provider is to call both the OpenConnection and EnsureCreated methods on the context’s Facade, else we’ll get DbUpdateException: “SQLite Error 1: ‘no such table: ” exception .

 

Limitations of In-Memory Databases

In-memory databases are great for unit testing and can really assist in providing the ability to re-create Unit Testing databases. However, there are a few limitations to using In-Memory databases like SqLite that you should be aware of. Particulary if the DbContext your project is using is configured to use some advanced Database features, this is due to the fact that most In-Memory databases do not support advanced Relational Database Management System (RDBMS) features.

RDBMS FeatureSupport
SchemaNONE
SequencesNone
Computed ColumnsDifferent
User Defined Functions (UDF)Different
Fragment Default ValuesDifferent
DatatypesDifferent

You should also check out SQLite EF Core Database Provider Limitations, as most of the limitations are a result of limitations in the underlying SQLite database engine and are not specific to EF Core.

You should exercise caution when developing tests making use of In-Memory databases especially if the conditions you’re testing explicitly make use of advanced database features. It is usually the case that you should reconsider your Unit testing strategy and confirm whether you are actually attemtpting to write Integration tests. Check out Roy Osheroves – The Art of Unit Testing: with examples in C#

Summary

Entity Framework core has made it really easy to set up and configure in-memory database options, reducing the amount of ceremony and configuration one has to do to get it up and running.

Being able to quickly and easily replicate and simulate database inteactivity in your Unit and Integration tests helps to ensure your code operates and functions as expected in ll conditions.

Gary Woodfine

Freelance Full Stack Developer at threenine.co.uk
Helps businesses by improving their technical proficiencies and eliminating waste from the software development pipelines.

A unique background as business owner, marketing, software development and business development ensures that he can offer the optimum business consultancy services across a wide spectrum of business challenges.
π