简体   繁体   English

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

[英]Instantiating an empty Entity Model without a DB connection for Unit Testing purposes

I want to write some unit tests for a method. 我想为一个方法编写一些单元测试。 However, the method references my entity framework. 但是,该方法引用了我的实体框架。 Here is a heavily contrived example of the method I want to test: 这是我想要测试的方法的一个非常人为的例子:

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

    return number;
}

The question: 问题:

Is there a way for me to instantiate a NWRevalDatabaseEntities object in my testing class without giving it a viable database connection , so all the tables are empty, and then just inserting the entities needed for the test, and never persisting them to a database? 有没有办法在我的测试类中实例化NWRevalDatabaseEntities对象而不给它一个可行的数据库连接 ,所以所有的表都是空的,然后只插入测试所需的实体,并且永远不会将它们持久化到数据库中?

The store for NWRevalDatabaseEntities is a SQLite database, and the auto generated constructors available are: 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();
}

All of which require a connection or connection string (or uses the stored connection string). 所有这些都需要连接或连接字符串(或使用存储的连接字符串)。

If this is not possible, I will look into creating an in-memory SQLite database and then feed that connection to the NWRevalDatabaseEntities constructor. 如果无法做到这一点,我将研究创建一个内存中的SQLite数据库,然后将该连接提供给NWRevalDatabaseEntities构造函数。 However, this seems like it would be much slower (since it hits the database engine) and unit testing should be fast, and also, will require me to get the database definition code into my application, where it was not previously needed. 但是,这似乎会慢得多(因为它会影响数据库引擎)并且单元测试应该很快,并且还需要我将数据库定义代码放入我的应用程序中,以前不需要它。

I know testing anything with entity frameworks usually go to integration testing, not unit testing. 我知道用实体框架测试任何东西通常都是集成测试,而不是单元测试。 However, these tests don't really test integration - the database query is incredibly simplistic and might as well have been against an array - I just want to check that the right selection of query is made by my method. 但是,这些测试并没有真正测试集成 - 数据库查询非常简单,并且可能也反对数组 - 我只想检查我的方法是否正确选择了查询。

Is there a way for me to instantiate a NWRevalDatabaseEntities object in my testing class without giving it a viable database connection, so all the tables are empty, and then just inserting the entities needed for the test, and never persisting them to a database? 有没有办法在我的测试类中实例化NWRevalDatabaseEntities对象而不给它一个可行的数据库连接,所以所有的表都是空的,然后只插入测试所需的实体,并且永远不会将它们持久化到数据库中?

No. 没有。

However, this seems like it would be much slower (since it hits the database engine) and unit testing should be fast, and also, will require me to get the database definition code into my application, where it was not previously needed. 但是,这似乎会慢得多(因为它会影响数据库引擎)并且单元测试应该很快,并且还需要我将数据库定义代码放入我的应用程序中,以前不需要它。

But your method is dependent on EF so you should test that it work with EF = with database. 但是你的方法依赖于EF,所以你应该测试它与EF = with database一起工作。

I know testing anything with entity frameworks usually go to integration testing, not unit testing. 我知道用实体框架测试任何东西通常都是集成测试,而不是单元测试。 However, these tests don't really test integration - the database query is incredibly simplistic and might as well have been against an array - I just want to check that the right selection of query is made by my method. 但是,这些测试并没有真正测试集成 - 数据库查询非常简单,并且可能也反对数组 - 我只想检查我的方法是否正确选择了查询。

Simplistic or not, it is a database query using Linq-to-entities. 简单与否,它是使用Linq-to-entities的数据库查询。 It is not an array query using Linq-to-objects. 它不是使用Linq-to-objects的数组查询。 This query is also very simplistic: entities.TableOfNumbers.Last() - it works on array but doesn't work with EF. 这个查询也非常简单: entities.TableOfNumbers.Last() - 它适用于数组,但不适用于EF。 If you don't want to test your query, separate it from the method you want to test: 如果您不想测试查询,请将其与要测试的方法分开:

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

Now you just need to find how to replace ExecuteQuery method for test. 现在您只需要找到如何替换ExecuteQuery方法进行测试。 You can make it protected virtual and override it for test because the only thing you want to test is that it receives correct Name parameter and that your GetNumberWithName returns the same number it received from ExecuteQuery . 您可以将其protected virtual并覆盖它以进行测试,因为您要测试的唯一事情是它接收正确的Name参数,并且您的GetNumberWithName返回从ExecuteQuery接收的相同数字。

Now you just need to write integration test for ExecuteQuery to verify that Linq query works with EF. 现在,您只需要为ExecuteQuery编写集成测试,以验证Linq查询是否适用于EF。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM