我应该如何设置集成测试以将测试数据库与Entity Framework一起使用?

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)

我应该补充一点,我发现这篇关于实体框架的博客文章有助于更深入地了解实体框架正在做什么/按照惯例.

  • @Sonofblip已经有一段时间了,但我怀疑我可能已经创建了DbContext的子类,因为我需要覆盖一些行为.如果您只使用DbContext,它是否有效? (2认同)

Jus*_*vey 5

只需在单元测试项目的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)


pet*_*kyy 5

如果您使用的是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连接字符串.

  • 您可以使用其他数据库进行测试.为此,只需在测试程序集的app.config中更新连接字符串.使用与MVC应用程序中相同的连接字符串名称,但更新数据库名称/凭据等.如果您的测试程序集没有app.config,您可以手动添加它. (3认同)