Avoid HasData Seed DbContext in EF Core 2.2 during Unit Tests

asp.net-core entity-framework-core sqlite unit-testing xunit

Question

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?

1
2
3/26/2019 9:07:53 PM

Popular Answer

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).

0
2/21/2020 1:00:04 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow