我正在为应用程序编写集成测试,但找不到任何关于如何为我的集成套件设置测试数据库的最佳实践。我正在使用实体框架代码优先的 ASP.NET MVC4 应用程序。
我可以确认我的测试项目中的测试默认与我机器上的本地开发数据库通信。这并不理想,因为我希望每次运行测试时都有一个新的数据库。
如何设置我的测试项目,以便我的测试与单独的实例通信?我假设可以设置 SQL Server Compact Edition 实例,但我不确定如何配置它。
我正在为应用程序编写集成测试,但找不到任何关于如何为我的集成套件设置测试数据库的最佳实践。我正在使用实体框架代码优先的 ASP.NET MVC4 应用程序。
我可以确认我的测试项目中的测试默认与我机器上的本地开发数据库通信。这并不理想,因为我希望每次运行测试时都有一个新的数据库。
如何设置我的测试项目,以便我的测试与单独的实例通信?我假设可以设置 SQL Server Compact Edition 实例,但我不确定如何配置它。
非常感谢@Justin 和@Petro 的回答,这对我帮助很大。我提出的解决方案是您建议的技术的组合。下面描述的解决方案为每次运行测试提供了一个新数据库,并为每个测试提供了一个单独的事务。
我在我的测试项目的 App.config 中为我的测试数据库添加了一个连接字符串:
<connectionStrings>
<add name ="TestDatabase"
providerName="System.Data.SqlClient"
connectionString="Data Source=(LocalDb)\v11.0;Database=TestDatabase;Integrated Security=True"/>
</connectionStrings>
我为我的集成测试创建了一个基类,以提供设置和拆卸。安装程序实例化上下文,如果数据库尚不存在则创建数据库并启动事务。Teardown 回滚事务。
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();
}
}
最后,我有一个类负责在所有测试运行后删除数据库:
[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);
}
}
我应该补充一点,我发现这篇关于 Entity Framework 的博客文章有助于更深入地了解 Entity Framework 在幕后/按照惯例在做什么。
只需在单元测试项目的 app.config 中设置一个指向新数据库实例的连接字符串。
然后,您可以使用测试类中的初始化和清理方法来创建和删除数据库。
连接字符串只是通常的,例如
<add name="UnitTestDBConnection" connectionString="Data Source=(local);Initial Catalog=UnitTestDB;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/>
然后创建数据库,每次测试一次,你可以这样做:
YourContext _ctx;
[TestInitialize]
public void Initiaslise()
{
YourNameDbInitialise initialiser = new YourNameDbInitialiseForTest();
Database.SetInitializer(initialiser);
_ctx = new YourNameContext();
initialiser.InitializeDatabase(_ctx);
}
并在每次测试结束时删除
[TestCleanup]
public void Cleanup()
{
Database.Delete("YourName");
}
如果您使用的是 NUnit,您可以使用Setup/Teardown
属性 withTransactionScope
来不将您的更改提交到数据库:
[SetUp]
public void SetUp()
{
transaction = new TransactionScope();
}
[TearDown]
public void TearDown()
{
if(transaction != null)
transaction.Dispose();
}
如果您正在使用其他一些单元测试框架,它应该具有类似的属性。我建议DbItegrationTest
为您的所有集成测试装置创建一个基类,因此如果您从此类派生,所有测试方法都不会提交到数据库。
要为其他数据库配置实体框架,请在您的测试程序集中覆盖 db 连接字符串。