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

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

Question

I'm having an inconsistent behavior running Integration Test using Resharper 8.2, NUnit 2.6.4. Depending one how many test I select, sometime all passes and sometime just firsts and lasts. If instead I run each test singularly they all passes.

In this prototype I have use a base test class that wipe the database using an existing stored procedure (avoiding this step the result doesn't change) and then initialize the data.

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

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();
    }
}

Base test Class, inherited by all 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 custome Database Initializer Class

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);
}

Simple 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 idea?

Edits:

  • I added a simple test example
  • Running the tests using NUnit agent I have the same behavior
  • Debugging it seems that the seeding is done once only
  • Using SQL profiler I can see the DB reset and seed done only once at the beginning

@Steve Fenton Tests are failing because the database is empty so Testing to Read and Delete data doesn't work.

@Gert Arnold No.

SOLUTION

I found the solution, that (after all) is pretty obvious. Below you can see the final solution.

The key is the Database.SetInitializer that configure EF to initialize the database using the registered IDatabaseInitializers.

EF6 allow you to use Context.Database.Initialize(true); that forces the database to run all the initializers.

The boolean parameter set to True force to run the initializers even if those have been already run 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);
}

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

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

Accepted Answer

I found the solution, that (after all) is pretty obvious. Below you can see the final solution.

The key is the Database.SetInitializer that configure EF to initialize the database using the registered IDatabaseInitializers.

EF6 allow you to use Context.Database.Initialize(true); that forces the database to run all the initializers.

The boolean parameter set to True force to run the initializers even if those have been already run 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);
}

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

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