In-Memory Databases- Unit Testing With C#, EFCore and XUnit

Sometimes we struggle to unit test our repositories due to creating a record in the database, now with EF-Core In-Memory Database; you can test your repository with ease. We have created a small dummy project to demonstrate to you the same.

In-Memory Database

An In-Memory Database is a lightweight, fast database that resides entirely in memory. It’s particularly useful for unit testing because it allows you to simulate database operations without the overhead of a real database. EF Core provides an In-Memory Database provider that you can use to test your data access code.

To set up in-memory databases and unit testing with C#, EF Core, and xUnit; follow these steps.

  1. Set Up Your Project
    • Ensure you have the necessary NuGet packages installed.
      • `Microsoft.EntityFrameworkCore.InMemory`
      • `xUnit`
      • `xUnit.runner.visualstudio`
      • `Microsoft.NET.Test.Sdk`
  2. Configure In-Memory Database: In your test project, configure the in-memory database in your DbContext options. This allows you to use an in-memory database for testing purposes.
  3. Create Your DbContext: Define your DbContext class as you would for any EF Core application.
  4. Write Unit Tests: Use xUnit to write your unit tests. You can create a test class and use the [Fact] attribute to define individual test methods.
  5. Initialize the In-Memory Database in Tests: In your test methods, initialize the in-memory database and seed it with test data if necessary.
  6. Run Your Tests: Use the xUnit test runner to execute your tests and verify the behavior of your code.

Here’s a high-level overview of the process.

Install Packages

dotnet add package Microsoft.EntityFrameworkCore.InMemory
dotnet add package xunit
dotnet add package xunit.runner.visualstudio
dotnet add package Microsoft.NET.Test.Sdk

Configure DbContext

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }
    public DbSet<User> Users { get; set; }
}

Write Unit Tests

public class UserRepositoryTests
{
    [Fact]
    public void Create_ShouldReturnSuccess_WhenDataGiven()
    {
        int expectedUserId = 1; 
        string expectedUserName = “Test”;

        var options = new DbContextOptionsBuilder<ApplicationDbContext>()
            .UseInMemoryDatabase(databaseName: new Guid.NewGuid().ToString())
            .Options;

        using (var context = new ApplicationDbContext(options))
        {
            // Arrange: Seed data into the context
            context.Users.Add(new User { Id = expectedUserId, Name = expectedUserName });
            context.SaveChanges();

            // Act: Perform the action to be tested
            var actualUser  = context.Users.FirstOrDefault(e => e.Id == expectedUserId);

            // Assert: Verify the result
            Assert.NotNull(result);
            Assert.Equal(expectedUserName, actualUser.Name);
        }
    }
}

This setup allows you to test your EF Core code using an in-memory database, ensuring your tests are fast and isolated from your production database.

Output

Output

Benefits and Limitations

Benefits

  • Speed: In-memory databases are faster than real databases.
  • Isolation: Tests are isolated from each other, ensuring no side effects.
  • Simplicity: Easy to set up and use.

Limitations

  • Not a Real Database: It doesn’t enforce all constraints (e.g., foreign keys) like a real relational database.
  • Limited Features: Some database-specific features may not be supported.

Code is also available on Github: https://github.com/arpitsdotnet/RepositoryUnitTestingExample