2

我正在尝试使用 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);
}

编辑

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

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),它们就会出现,正如我在开始时所举例说明的那样。

4

1 回答 1

1

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

public MyTestClass()
{
    using (var db = new MyContext(GetDbConnection(), true))
    {
        db.Database.Initialize(false);
    }
}
于 2013-05-23T22:30:21.547 回答