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);
}
}
有什么想法吗?
编辑:
- 我添加了一个简单的测试例子
- 使用 NUnit 代理运行测试我有相同的行为
- 调试好像播种只做一次
- 使用 SQL 分析器我可以看到数据库重置和种子在开始时只完成一次
@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
我在使用 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);
}
}
有什么想法吗?
编辑:
- 我添加了一个简单的测试例子
- 使用 NUnit 代理运行测试我有相同的行为
- 调试好像播种只做一次
- 使用 SQL 分析器我可以看到数据库重置和种子在开始时只完成一次
@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