Just a litte example how to use Entity Framework Core Sqlite Provider in-memory database together with simple unit testing in ASP.NET Core and XUnit.

Similar posts

Lets assume we have the following setup.

An Entity Framework Core DbContext ToDoDbContext

public class ToDoDbContext : DbContext
{
    public DbSet<ToDoItem> ToDoItem { get; set; }

    public ToDoDbContext(DbContextOptions<ToDoDbContext> options)
        : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfigurationsFromAssembly(typeof(ToDoDbContext).Assembly);
    }
}

and a configuration ToDoItemConfiguration

class ToDoItemConfiguration : IEntityTypeConfiguration<ToDoItem>
{
    public void Configure(EntityTypeBuilder<ToDoItem> builder)
    {
        builder.HasKey(k => k.Id);
        builder.Property(p => p.Id).IsRequired().ValueGeneratedOnAdd();
        builder.Property(p => p.Name).IsRequired().HasMaxLength(128);
    }
}

for our model ToDoItem

public class ToDoItem
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

To test our configuration with an in-memory database we can use the Entity Framework Core Sqlite Provider. There is also an InMemory Provider for testing but

InMemory is designed to be a general purpose database for testing, and is not designed to mimic a relational database.

In our test project, we can create a base class for creating and disposing the in-memory Sqlite database.

public abstract class TestWithSqlite : IDisposable
{
    private const string InMemoryConnectionString = "DataSource=:memory:";
    private readonly SqliteConnection _connection;

    protected readonly ToDoDbContext DbContext;

    protected TestWithSqlite()
    {
        _connection = new SqliteConnection(InMemoryConnectionString);
        _connection.Open();
        var options = new DbContextOptionsBuilder<ToDoDbContext>()
                .UseSqlite(_connection)
                .Options;
        DbContext = new ToDoDbContext(options);
        DbContext.Database.EnsureCreated();
    }

    public void Dispose()
    {
        _connection.Close();
    }
}

To test our setup

public class ToDoDbContextTests : TestWithSqlite
{
    [Fact]
    public async Task DatabaseIsAvailableAndCanBeConnectedTo()
    {
        Assert.True(await DbContext.Database.CanConnectAsync());
    }
}

Now we can create our unit tests for our configuration

public class ToDoItemConfigurationTests : TestWithSqlite
{
    [Fact]
    public void TableShouldGetCreated()
    {
        Assert.False(DbContext.ToDoItem.Any());
    }

    [Fact]
    public void NameIsRequired()
    {
        var newItem = new ToDoItem();
        DbContext.ToDoItem.Add(newItem);

        Assert.Throws<DbUpdateException>(() => DbContext.SaveChanges());
    }

    [Fact]
    public void AddedItemShouldGetGeneratedId()
    {
        var newItem = new ToDoItem() { Name = "Testitem" };
        DbContext.ToDoItem.Add(newItem);
        DbContext.SaveChanges();

        Assert.NotEqual(Guid.Empty, newItem.Id);
    }

    [Fact]
    public void AddedItemShouldGetPersisted()
    {
        var newItem = new ToDoItem() { Name = "Testitem" };
        DbContext.ToDoItem.Add(newItem);
        DbContext.SaveChanges();

        Assert.Equal(newItem, DbContext.ToDoItem.Find(newItem.Id));
        Assert.Equal(1, DbContext.ToDoItem.Count());
    }
}

This project is available on github.