为单元测试目的实例化没有数据库连接的空实体模型

时间:2012-09-07 08:05:11

标签: c# unit-testing entity-framework-4 database-connection system.data.sqlite

我想为方法编写一些单元测试。但是,该方法引用了我的实体框架。这是我想要测试的方法的一个非常人为的例子:

public int GetNumberWithName(string name, NWRevalDatabaseEntities entities)
{
    int number = (from n in entities.TableOfNumbers
                    where n.Name == name
                    select n).First();

    return number;
}

问题:

我有没有办法在我的测试类中实例化NWRevalDatabaseEntities对象而不给它一个可行的数据库连接,所以所有的表都是空的,然后只插入实体测试需要,并且从不将它们保存到数据库中?

NWRevalDatabaseEntities的商店是一个SQLite数据库,可用的自动生成的构造函数是:

/// <summary>
/// Initializes a new NWRevalDatabaseEntities object using the connection string found in the 'NWRevalDatabaseEntities' section of the application configuration file.
/// </summary>
public NWRevalDatabaseEntities() : base("name=NWRevalDatabaseEntities", "NWRevalDatabaseEntities")
{
    this.ContextOptions.LazyLoadingEnabled = true;
    OnContextCreated();
}

/// <summary>
/// Initialize a new NWRevalDatabaseEntities object.
/// </summary>
public NWRevalDatabaseEntities(string connectionString) : base(connectionString, "NWRevalDatabaseEntities")
{
    this.ContextOptions.LazyLoadingEnabled = true;
    OnContextCreated();
}

/// <summary>
/// Initialize a new NWRevalDatabaseEntities object.
/// </summary>
public NWRevalDatabaseEntities(EntityConnection connection) : base(connection, "NWRevalDatabaseEntities")
{
    this.ContextOptions.LazyLoadingEnabled = true;
    OnContextCreated();
}

所有这些都需要连接或连接字符串(或使用存储的连接字符串)。

如果无法做到这一点,我将研究创建一个内存中的SQLite数据库,然后将该连接提供给NWRevalDatabaseEntities构造函数。但是,这似乎会慢得多(因为它会影响数据库引擎)并且单元测试应该很快,并且还需要我将数据库定义代码放入我的应用程序中,以前不需要它。

我知道使用实体框架测试任何东西通常都会进行集成测试,而不是单元测试。但是,这些测试并没有真正测试集成 - 数据库查询非常简单,并且可能反对数组 - 我只想检查我的方法是否正确选择了查询。

1 个答案:

答案 0 :(得分:2)

  

我有没有办法实例化NWRevalDatabaseEntities对象   在我的测试类中没有给它一个可行的数据库连接,所以   所有表都是空的,然后只需插入所需的实体   对于测试,从不将它们保存到数据库中?

没有

  

然而,这似乎会慢很多(因为它会打击   数据库引擎)和单元测试应该很快,而且也会   要求我将数据库定义代码放入我的应用程序中,   以前不需要的地方。

但是你的方法依赖于EF,所以你应该测试它是否适用于EF = with database。

  

我知道通常会使用实体框架来测试任何内容   集成测试,而不是单元测试。但是,这些测试并不适合   真正的测试集成 - 数据库查询非常简单   并且可能一直反对阵列 - 我只想检查   我的方法正确选择了查询。

简单与否,它是使用Linq-to-entities的数据库查询。它不是使用Linq-to-objects的数组查询。此查询也非常简单:entities.TableOfNumbers.Last() - 它适用于数组,但不适用于EF。如果您不想测试查询,请将其与您要测试的方法分开:

public int GetNumberWithName(string name, NWRevalDatabaseEntities entities)
{
    int number = ExecuteQuery(entities, Name);
    return number;
}

现在您只需要找到如何替换ExecuteQuery方法进行测试。您可以将其设为protected virtual并覆盖它以进行测试,因为您要测试的唯一内容是它接收到正确的Name参数,并且您的GetNumberWithName返回从{ExecuteQuery收到的相同数字1}}。

现在您只需编写ExecuteQuery的集成测试,以验证Linq查询是否适用于EF。