DEV Community

Paul Michaels
Paul Michaels

Posted on

2 1

Unit Testing With Entity Framework and Entity Framework Core 2.1

Entity Framework Core 2.1 comes with a nifty little feature: an In Memory Database setting. What this means, is that with a single option setting, your tests can interact directly with the database (or at least EF's impression of the database) but not actually touch any physical database. In other words, you can write unit tests for data access; an example:

// Arrange
DbContextOptions<ApplicationDbContext> options = new DbContextOptionsBuilder<ApplicationDbContext>()
    .UseInMemoryDatabase(Guid.NewGuid().ToString())
    .EnableSensitiveDataLogging()                
    .Options;

using (var context = new ApplicationDbContext(options))
{
    context.Database.EnsureDeleted();
    ResourceCategory resourceCategory = new ResourceCategory()
    {
        Name = "TestCategory"
    }
};

// Act
_applicationDbContext.ResourceCategories.Add(resourceCategory);
_applicationDbContext.SaveChanges();

// Assert                
Assert.Equal("TestCategory", context.ResourceCategories.First().Name);               

To just quickly explain what this is doing: we have a DbContext called ApplicationDbContext and we're building a set of options on top of that context. We're then instantiating the context and cleaning the in memory database. Finally, we're adding a new piece of data to the context and then asserting that it has been added.

Told you it was nifty.

But what about if you're still using Entity Framework 6?

Glad you asked.

Out of the box, EF does not come with this kind of functionality; however, I recently came across (and contributed) to a NuGet library that provides just such a facility. It provides a wrapper for both Moq and Nsubstitute. The GitHub Repo is here.

This was originally posted here

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (2)

Collapse
 
andres profile image
Andrés Pérez • • Edited

I have used a different approach, not sure what are your thoughts on it:

public class BaseTest
{
    protected readonly ApplicationDbContext _context;

    public BaseTest()
    {
        var options = new DbContextOptionsBuilder<ApplicationDbContext>()
            .UseInMemoryDatabase(Guid.NewGuid().ToString())
            .Options;

        _context = new ApplicationDbContext(options);

        _context.Database.EnsureCreated();
    }
}

Then in my tests, I inherit from that base class:

public class SomeClassTest : BaseTest, IDisposable
{
    public void Dispose()
    {
        _context.Database.EnsureDeleted();
    }

    [Fact]
    public async Task SomeTest()
    {
        // Here you have access to your _context as usual
        // Arrange
        // Act
        // Assert
    }
}
Collapse
 
pcmichaels profile image
Paul Michaels •

I do like this approach, you can also use the test framework 'setup' method (in XUnit it's just the class constructor).

Personally, though, if I was going down this kind of path, I'd probably put the set-up into a static helper method, rather than using inheritance. IMHO it gives better readability to the test.

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more