Entity Framework 集成测试运行多个单独通过的测试失败 [Resharper、NUnit、EF6]

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

我在使用 Resharper 8.2、NUnit 2.6.4 运行集成测试时遇到了不一致的行为。 取决于我选择了多少测试,有时全部通过,有时只是第一次和最后一次。 相反,如果我单独运行每个测试,它们都会通过。

在这个原型中,我使用了一个基础测试 class,它使用现有的存储过程擦除数据库(避免这一步,结果不会改变),然后初始化数据。

下面的 Class 用于播种基于构建器和实体的数据库。

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

基础测试Class,由所有测试继承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();
        }
    }
}

客户数据库初始化器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);
}

简单测试

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

有什么想法吗?

编辑:

@Steve Fenton 测试失败,因为数据库是空的,所以读取和删除数据的测试不起作用。

@Gert Arnold

解决方案

我找到了解决方案,(毕竟)很明显。 下面你可以看到最终的解决方案。

关键是 Database.SetInitializer 配置 EF 使用注册的 IDatabaseInitializers.[=17= 初始化数据库]

EF6 允许您使用 Context.Database.Initialize(true); 强制数据库运行所有初始化程序。

布尔参数设置为 True 强制运行初始化程序,即使这些初始化程序已经针对当前上下文运行。

[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

我找到了解决方案,(毕竟)很明显。下面你可以看到最终的解决方案。

关键是 Database.SetInitializer 配置 EF 使用注册的 IDatabaseInitializers.[=12= 初始化数据库]

EF6 允许您使用 Context.Database.Initialize(true); 强制数据库 运行 所有初始化程序。

设置为 True 的布尔参数强制 运行 初始值设定项,即使它们已经 运行 当前上下文。

[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