[英]How should I set up my integration tests to use a test database with Entity Framework?
I am writing integration tests for an application and have not been able to find any best practices on how to set up a test database for my integration suite. 我正在为应用程序编写集成测试,并且无法找到有关如何为我的集成套件设置测试数据库的最佳实践。 I am working on an ASP.NET MVC4 application using Entity Framework code-first. 我正在使用实体框架代码优先处理ASP.NET MVC4应用程序。
I can confirm that the tests in my test project talk to the local development database on my machine by default. 我可以确认我的测试项目中的测试默认与我的机器上的本地开发数据库通信。 This is not ideal, as I want to have a fresh database every time I run the tests. 这并不理想,因为我希望每次运行测试时都有一个新的数据库。
How can I set up my test project so that my tests talk to a separate instance? 如何设置我的测试项目以便我的测试与单独的实例进行通信? I'm assuming that it is possible to set up an SQL Server Compact Edition instance, but I'm not sure how to configure this. 我假设可以设置SQL Server Compact Edition实例,但我不知道如何配置它。
Thanks so much to @Justin and @Petro for your answers, which have helped me immensely. 非常感谢@Justin和@Petro的回答,这对我帮助很大。 The solution I have come up with is a combination of the techniques you suggested. 我提出的解决方案是您建议的技术的组合。 The solution described below provides a new database for each run of the tests, and a separate transaction for each test. 下面描述的解决方案为每次测试运行提供了一个新数据库,并为每个测试提供了一个单独的事务。
I added a connection string for my test database in the App.config of my Test project: 我在我的Test项目的App.config中为我的测试数据库添加了一个连接字符串:
<connectionStrings>
<add name ="TestDatabase"
providerName="System.Data.SqlClient"
connectionString="Data Source=(LocalDb)\v11.0;Database=TestDatabase;Integrated Security=True"/>
</connectionStrings>
I created a base class for my integration tests, to provide setup and teardown. 我为集成测试创建了一个基类,以提供设置和拆卸。 Setup instantiates the context, creates the DB if it doesn't exist yet and starts a transaction. 安装程序实例化上下文,如果它尚不存在则创建数据库并启动事务。 Teardown rolls back the transaction. 拆解回滚交易。
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();
}
}
Finally, I have a class that takes care of deleting the database after all the tests have run: 最后,我有一个类在所有测试运行后负责删除数据库:
[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);
}
}
I should add that I found this blog post about Entity Framework useful for a deeper understanding of what Entity Framework is doing under the hood / by convention. 我应该补充一点,我发现这篇关于实体框架的博客文章有助于更深入地了解实体框架正在做什么/按照惯例。
Just setup a connection string in the app.config of your unit test project that points to the new DB instance. 只需在单元测试项目的app.config中设置一个指向新数据库实例的连接字符串。
You can then use the initialisation and cleanup methods in your test class to create and delete the DB. 然后,您可以使用测试类中的初始化和清理方法来创建和删除数据库。
The connection string is just the usual, eg 连接字符串就是常见的,例如
<add name="UnitTestDBConnection" connectionString="Data Source=(local);Initial Catalog=UnitTestDB;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/>
Then to create the DB, once per test, you could do: 然后创建数据库,每次测试一次,你可以做:
YourContext _ctx;
[TestInitialize]
public void Initiaslise()
{
YourNameDbInitialise initialiser = new YourNameDbInitialiseForTest();
Database.SetInitializer(initialiser);
_ctx = new YourNameContext();
initialiser.InitializeDatabase(_ctx);
}
and this to delete at the end of each test 这将在每次测试结束时删除
[TestCleanup]
public void Cleanup()
{
Database.Delete("YourName");
}
If you are using NUnit, you could use Setup/Teardown
attribute with TransactionScope
to not commit your changest to the database: 如果您使用的是NUnit,则可以使用TransactionScope
Setup/Teardown
属性不将更改提交到数据库:
[SetUp]
public void SetUp()
{
transaction = new TransactionScope();
}
[TearDown]
public void TearDown()
{
if(transaction != null)
transaction.Dispose();
}
If you are using some other unit test framework it should have simmilar attributes. 如果您正在使用其他一些单元测试框架,它应具有类似的属性。 I would recomend creating a base class DbItegrationTest
for all your integration test fixtures so if you derive from this class all test methods won't do commits to database. 我建议为所有集成测试装置创建一个基类DbItegrationTest
,所以如果从这个类派生,所有测试方法都不会对数据库进行提交。
To configure Entity Framework for other database please override db connection string in your test assembly. 要为其他数据库配置Entity Framework,请覆盖测试程序集中的db连接字符串。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.