Entity Framework Integration tests failing running multiple tests that are singularly passing [Resharper, NUnit, EF6]

c# entity-framework-6 integration-testing nunit resharper

Question

Running an Integration Test with Resharper 8.2 and NUnit 2.6.4 results in inconsistent behavior for me. Depending on how many tests I choose, sometimes everyone succeeds and sometimes only the top two do. Instead, if I run each test separately, they all succeed.

In this prototype, I've used a base test class to first setup the data before using an existing stored procedure to wipe the database clean.

Below is the Builders and Entities-based Class used to seed the database.

public class DefaultTestData<TB, TE> : ITestData where TB:BaseBuilder<TB, TE>
{
    public void Seed(DbContext context)
    {
        context.Set(typeof (TE)).Add(((TB) Activator.CreateInstance(typeof (TB))).Build());
        context.Set(typeof (TE)).Add(((TB) Activator.CreateInstance(typeof (TB))).Build());
        context.SaveChanges();
    }
}

Every test class inherits from the base test class.

[TestFixture]
public abstract class BaseTest
{
    protected FmsDbContext Context = null;

    public abstract ITestData InitializeData();

    [Test]
    public abstract void Mapping();

    [Test]
    public abstract void Delete();

    [SetUp]
    public virtual void SetupInitialData()
    {
        var data = InitializeData();
        Context = new FmsDbContext();
        // Context.Database.Initialize(true); -- Using initialize One or Zero test runs

        if (data != null)
        {
            Database.SetInitializer(new TestDataInitializer(data));
        }
    }

    [TearDown]
    public virtual void Teardown()
    {
        if (Context != null)
        {
            Context.Dispose();
        }
    }
}

The custom initializer class for databases

public class TestDataInitializer : IDatabaseInitializer<FmsDbContext>
{
    private readonly ITestData _data;

    public TestDataInitializer(ITestData data)
    {
        _data = data;
    }

    private void Seed(DbContext context)
    {
        if(_data != null)
            _data.Seed(context);
    }

    public void InitializeDatabase(FmsDbContext context)
    {
        context.Database.ExecuteSqlCommand("EXEC [dbo].[uspWipeDatabase]");
        Seed(context);
    }
}

public interface ITestData
{
    void Seed(DbContext context);
}

easy test

[TestFixture]
public class TagTest : BaseTest
{
    public override ITestData InitializeData()
    {
        return new DefaultTestData<TagBuilder, Tag>();
    }

    [Test]
    public override void Mapping()
    {
        var tag = Context.Tags.FirstOrDefault();
        Assert.NotNull(tag);
    }

    [Test]
    public override void Delete()
    {
        var initialCount = Context.Tags.Count();
        var tag = Context.Tags.FirstOrDefault();
        Context.Tags.Remove(tag);
        Context.SaveChanges();

        Assert.AreEqual(Context.Tags.Count(), initialCount - 1);
    }
}

Any ideas?

Edits:

  • I included a basic test case.
  • I have the same behavior when I run the tests using the NUnit agent.
  • According to debugging, the seeding is only performed once.
  • I can see that the DB reset and seed were only performed once at the beginning using SQL profiler.

Stephen Fenton Testing to Read and Delete data doesn't work because the database is empty, which causes tests to fail.

Gerald Arnold No.

SOLUTION

I discovered the answer, which is really rather obvious. The complete answer is displayed below.

The crucial Database.SetInitializer is what instructs EF to use the registered IDatabaseInitializers to initialize the database.

You can use the Context.Database.Initialize(true); command in EF6 to make the database run all initializers.

When the boolean option is set to True, the initializers are forced to run even if they have already done so for the current context.

[SetUp]
public virtual void SetupInitialData()
{
    var data = InitializeData();
    Context = new FmsDbContext();

    if (data != null)
    {
        Database.SetInitializer(new TestDataInitializer(data));
    }

    Context.Database.Initialize(true);
}

http://msdn.microsoft.com/en-us/library/system.data.entity.database.initialize%28v=vs.113%29.aspx for more information

1
2
1/3/2015 6:17:23 PM

Accepted Answer

ZZZ_tmp
3
1/3/2015 6:24:31 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