Entity Framework Core :
.NET Framework / EF Core 3.1 / Sqlite / xunit

Entity Framework Core permet d'exécuter des tests unitaires par l'intermédiaire de Sqlite. Cela fonctionne simplement en .NET Core, mais en .NET Framework, c'est une autre histoire.

Portail abandonné en forét
Portail abandonné en forét

Avertissement : Entity Framework Core 3.1 n'est plus supporté.

Problème

Lorsque l'on créait un projet créait un projet de test unitaire avec Entity Framework Core Sqlite en .NET Framework :

dotnet new xunit --name Demo.Tests --framework netcoreapp3.1 --target-framework-override net48
cd Demo.Tests
dotnet add package Microsoft.EntityFrameworkCore.Sqlite --version 3.1.31
dotnet restore --ignore-failed-sources
dotnet test

Puisque l'on écrit un test utilisant Sqlite. Par exemple :

using Microsoft.EntityFrameworkCore;
using Xunit;

namespace Demo.Tests
{
    public class UnitTest1
    {
        [Fact]
        public void Test1()
        {
            var context = new DemoContext();
            context.Database.EnsureCreated();
        }
    }

    public class DemoContext : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlite("Data Source=:memory:");
        }
    }
}

Lorsque le test est exécuté :

> dotnet test
...
[xUnit.net 00:00:02.62]     Demo.Tests.UnitTest1.Test1 [FAIL]
  Failed Demo.Tests.UnitTest1.Test1 [1 s]
  Error Message:
   System.TypeInitializationException : The type initializer for 'Microsoft.Data.Sqlite.SqliteConnection' threw an exception.
---- System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
-------- System.Exception : Library e_sqlite3 not found
...
Failed!  - Failed:     1, Passed:     0, Skipped:     0, Total:     1, Duration:  - Demo.Tests.dll (net48)

L'erreur "Library e_sqlite3 not found" survient.

Analyse

Ce problème est référencé dans le ticket GitHub :
[.Net Framework 4.8]Library e_sqlite3 not found

En résumé, l'exécuteur de test xunit exécute les tests en Shadow Copy par défaut... seulement les composants nécessaires à Sqlite ne semblent pas correctement copiés.

Shadow Copy, quésaco?

En .NET, lorsqu'un assemblie est chargé, le fichier associé est verrouillé et il n'est pas possible de le modifier.

Le Shadow Copy indique à la runtime d'effectuer une copie des assemblies dans un dossier temporaire pour les charger depuis ce dossier. Ainsi le fichier originel n'est pas verrouillé.

Solution

Pour éviter ce problème, il suffit de désactiver le Shadow Copy à l'exécution des tests. Pour cela, il faut ajouter au côté du csproj le fichier "xunit.runner.json" avec le contenu suivant :

{
  "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
  "shadowCopy": false
}

One possible testing approach is to swap your production database with SQLite, effectively using it as a testing "fake".


Une approche possible pour tester consiste à substituer le système de gestion de base de données (SGBD) par SQLite, en l'utilisant comme une base de données factice.