rou*_*uan 22 c# asp.net-mvc integration-testing entity-framework ef-code-first
我正在为应用程序编写集成测试,并且无法找到有关如何为我的集成套件设置测试数据库的最佳实践.我正在使用实体框架代码优先处理ASP.NET MVC4应用程序.
我可以确认我的测试项目中的测试默认与我的机器上的本地开发数据库通信.这并不理想,因为我希望每次运行测试时都有一个新的数据库.
如何设置我的测试项目以便我的测试与单独的实例进行通信?我假设可以设置SQL Server Compact Edition实例,但我不知道如何配置它.
rou*_*uan 24
非常感谢@Justin和@Petro的回答,这对我帮助很大.我提出的解决方案是您建议的技术的组合.下面描述的解决方案为每次测试运行提供了一个新数据库,并为每个测试提供了一个单独的事务.
我在我的Test项目的App.config中为我的测试数据库添加了一个连接字符串:
<connectionStrings>
<add name ="TestDatabase"
providerName="System.Data.SqlClient"
connectionString="Data Source=(LocalDb)\v11.0;Database=TestDatabase;Integrated Security=True"/>
</connectionStrings>
Run Code Online (Sandbox Code Playgroud)
我为集成测试创建了一个基类,以提供设置和拆卸.安装程序实例化上下文,如果它尚不存在则创建数据库并启动事务.拆解回滚交易.
public class EntityFrameworkIntegrationTest
{
protected MyDbContext DbContext;
protected TransactionScope TransactionScope;
[TestInitialize]
public void TestSetup()
{
DbContext = new MyDbContext(TestInit.TestDatabaseName);
DbContext.Database.CreateIfNotExists();
TransactionScope = new TransactionScope(TransactionScopeOption.RequiresNew);
}
[TestCleanup]
public void TestCleanup()
{
TransactionScope.Dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
最后,我有一个类在所有测试运行后负责删除数据库:
[TestClass]
public static class TestInit
{
// Maps to connection string in App.config
public const string TestDatabaseName = "TestDatabase";
[AssemblyCleanup]
public static void AssemblyCleanup()
{
Database.Delete(TestDatabaseName);
}
}
Run Code Online (Sandbox Code Playgroud)
我应该补充一点,我发现这篇关于实体框架的博客文章有助于更深入地了解实体框架正在做什么/按照惯例.
只需在单元测试项目的app.config中设置一个指向新数据库实例的连接字符串.
然后,您可以使用测试类中的初始化和清理方法来创建和删除数据库.
连接字符串就是常见的,例如
<add name="UnitTestDBConnection" connectionString="Data Source=(local);Initial Catalog=UnitTestDB;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/>
Run Code Online (Sandbox Code Playgroud)
然后创建数据库,每次测试一次,你可以做:
YourContext _ctx;
[TestInitialize]
public void Initiaslise()
{
YourNameDbInitialise initialiser = new YourNameDbInitialiseForTest();
Database.SetInitializer(initialiser);
_ctx = new YourNameContext();
initialiser.InitializeDatabase(_ctx);
}
Run Code Online (Sandbox Code Playgroud)
这将在每次测试结束时删除
[TestCleanup]
public void Cleanup()
{
Database.Delete("YourName");
}
Run Code Online (Sandbox Code Playgroud)
如果您使用的是NUnit,则可以使用Setup/Teardownattribute with TransactionScope来不将更改提交到数据库:
[SetUp]
public void SetUp()
{
transaction = new TransactionScope();
}
[TearDown]
public void TearDown()
{
if(transaction != null)
transaction.Dispose();
}
Run Code Online (Sandbox Code Playgroud)
如果您正在使用其他一些单元测试框架,它应具有类似的属性.我会建议建立一个基类DbItegrationTest为您的所有集成测试夹具,所以如果你从这个类中的所有测试方法不会做得出致力于数据库.
要为其他数据库配置Entity Framework,请覆盖测试程序集中的db连接字符串.