用例:我们有一个很大的数据库(约200个表),用于大型(传统)系统。它以数据库优先方式实现,其中一个edmx文件定义了整个数据库。我们正在使用XUnit和Effort进行自动测试。问题在于这些测试非常缓慢。即使测试覆盖范围与我们希望的范围相去甚远,我们当前的测试套件也需要大约7-8分钟的时间来运行。
我注意到,如果我创建edmx文件的较小子集,则通过删除一些不需要的表,测试运行会更快。
我正在寻找一种解决方案,在该解决方案中,对于特定测试或一组测试,我们可以通过某种方式使Effort仅创建所需表的子集(我认为在许多情况下,我们只需要一个表)。
目前,我们正在建立这样的连接:
connection = EntityConnectionFactory.CreateTransient("metadata=res://entities.csdl|res://entities.ssdl|res://entities.msl");
有什么办法(例如,通过在运行时中运行XML转换)使Effort仅创建我们定义的表子集所需的数据结构?
免责声明 :我是项目Entity Framework Effort的所有者
我们的库具有允许创建还原点并回滚到它的功能。
因此,使用此技巧,您可以在创建所有表时仅使用CreateRestorePoint()
一次,然后对于每个测试,均使用RollbackToRestorePoint
启动它们。 (还有其他几种方法可以使它起作用,但是我想您明白了)
毫无疑问,这将使您的测试运行更快,因为不必每次都创建表。
这是一个例子:
var conn = Effort.DbConnectionFactory.CreateTransient();
using (var context = new EntityContext(conn))
{
context.EntitySimples.Add(new EntitySimple { ColumnInt = 1 });
context.EntitySimples.Add(new EntitySimple { ColumnInt = 2 });
context.EntitySimples.Add(new EntitySimple { ColumnInt = 3 });
context.SaveChanges();
}
// Create a RestorePoint that will save all current entities in the "Database"
conn.CreateRestorePoint();
// Make any change
using (var context = new EntityContext(conn))
{
context.EntitySimples.RemoveRange(context.EntitySimples);
context.SaveChanges();
}
// Rollback to the restore point to make more tests
conn.RollbackToRestorePoint();
分开进行单元测试和集成测试。对于集成测试,可以使用数据库并在更高的环境上运行(以节省时间),但是在本地环境上,可以使用Faker \ Bogus和NBuilder生成大量数据进行单元测试。
https://dzone.com/articles/using-faker-and-nbuilder-to-generate-massive-data
另一个选择是您可以创建与您的单元测试用例相对应的资源文件https://www.danylkoweb.com/Blog/the-fastest-way-to-mock-a-database-for-unit-testing-B6
我还想让您了解InMemoryDB与SqlLite的性能, http://www.mukeshkumar.net/articles/efcore/unit-testing-with-inmemory-provider-and-sqlite-in-memory-database-in- ef-core
尽管以上示例是针对EFCore的,但在EF6中,我们也可以使用SqlLite https://www.codeproject.com/Tips/1056400/Setting-up-SQLite-and-Entity-Framework-Code-First
因此,我建议您使用sqllite进行集成测试方案。对于单元测试,可以使用sqllite或Faker \ Bogus和NBuilder。
希望能帮助到你!