Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoid HasData Seed DbContext in EF Core 2.2 during Unit Tests

In my ASP.Net CORE 2.2/EF Core 2.2 web API app, I have a HasData() method in my DbContext to seed the DB with some standard data that I use. However, I don't want to use that data when running my xUnit tests.

My unit tests use the Sqlite in-memory provider and as part of that process, it requires a call to EnsureCreated(). Well, EnsureCreated() calls OnModelCreating() which calls HasData(), so my unit test context now contains all of my HasData seed data, which I don't want. I want to seed my unit tests with different, very specific data.

Because EnsureCreated() seeds the context, and then I try adding my unit test specific seed data, I end up with both sets of data in my test DbContext and my tests fail.

How can I bypass the HasData call for my unit tests?

like image 392
Bryan Lewis Avatar asked Oct 28 '25 20:10

Bryan Lewis


1 Answers

Instead of trying to bypass HasData(), you could instead conditionally not supply data to that method.

Quick example - if you move the pre-pop data out to e.g. "DataInitialiser" classes:

 builder.HasData(new UserDataInitialiser().Data); 

Then set a static flag in a base class:

public abstract class DataInitialiserControl
{
    public static bool SkipInitData { get; set; } // ** flag **
}

public abstract class DataInitialiser<T> : DataInitialiserControl
{
    public IList<T> Data => SkipInitData ? new List<T>() : GetData();

    protected abstract IList<T> GetData();
}

Your DataInitialisers would look like this:

public class UserDataInitialiser : DataInitialiser<User>
{
    protected override IList<User> GetData()
    {
        return new[]
        {
            new User {Id = 1, Name = "Bob"}
        };
    }
}

You could then just set the static flag in your test initialisation:

public abstract class TestBase
{
    protected DbContextOptions<MyContext> DbOptions { get; private set; }

    [TestInitialize]
    public void InitializeDatabase()
    {
        // ** SKIP DATA PRE-POP **
        DataInitialiserControl.SkipInitData = true;

        DbOptions = BuildDbContextOptions(new DbContextOptionsBuilder<MyContext>()).Options;

        using (var context = GetContext())
        {
            context.Database.EnsureCreated();
        }
    }

    [TestCleanup]
    public void ClearDatabase()
    {
        using (var context = GetContext())
        {
            context.Database.EnsureDeleted();
        }
    }
}

(Code untested, but should be more or less right).

like image 73
jimasp Avatar answered Oct 31 '25 10:10

jimasp



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!