在单元测试中重用DbContext实例之间的连接

时间:2013-04-26 19:58:57

标签: entity-framework sql-server-ce xunit.net

我正在尝试使用EntityFramework 5,SQL Server Compact 4和Xunit设置一些单元测试。

我正在使用不同的上下文实例,因为我正在测试ASP MVC应用程序,我需要测试一些更新操作在分离实体上的行为。

[Fact, AutoRollback]
public void TestConnection()
{
    using (var connection = this.GetDbConnection())
    {
        using (var context = new MyContext(connection, false))
        {
            // Do database stuff
        }

        using (var context = new MyContext(connection, false))
        {
            // Do database stuff
        }
    }
}

public DbConnection GetDbConnection()
{
    string dataSource = "|DataDirectory|\\MyDb.sdf";

    var sqlBuilder = new SqlCeConnectionStringBuilder();
    sqlBuilder.DataSource = dataSource;

    return new SqlCeConnection(sqlBuilder.ToString());
}

这给了我以下错误:

System.Data.EntityException : The underlying provider failed on Open.
System.InvalidOperationException : The connection object can not be enlisted in transaction scope.

我知道我无法在TransactionScope中打开多个DbContext实例(这可能是Xunit在你的方法中放置FallbackAttribute时所做的事情),所以这就是我之前创建连接的原因。

如果我尝试自己打开连接,它仍然无效:

using (var connection = this.GetDbConnection())
{
    connection.Open();

    using (var context = new MyContext(connection, false))
    {

我得到以下异常:

System.ArgumentException : EntityConnection can only be constructed with a closed DbConnection.

有人知道如何解决这个问题吗?

修改

处理Db的测试类扩展了一个“DomainFactsBase”,数据库初始化如下:

public DomainFactsBase()
{
    Database.SetInitializer(new DropCreateDatabaseIfModelChanges<MyContext>());
    using (var context = new MyContext(GetDbConnection(), true))
        context.Database.Initialize(false);
}

修改

当我只创建一个上下文实例时,我可以使用autorollback成功运行测试。这是按照this article中的说明完成的。我有一个扩展方法:

public static void OpenConnection(this DbContext context)
{
    ((IObjectContextAdapter)context).ObjectContext.Connection.Open();
}

我在测试中创建上下文后立即调用它:

[Fact, AutoRollback]
public void SomeFact()
{
    using (var context = new MyContext())
    {
        context.OpenConnection();

            // Do stuff
    }
}

这项工作毫无问题。当我尝试在同一事实中多次打开上下文时(启用了AutoRollback),就会出现这些内容,正如我在开头所做的那样。

1 个答案:

答案 0 :(得分:1)

在测试之外初始化数据库。您可以在测试类的构造函数中执行此操作。

public MyTestClass()
{
    using (var db = new MyContext(GetDbConnection(), true))
    {
        db.Database.Initialize(false);
    }
}