unit testing数据访问层的方法

我一直试图寻找一种有效的方法来在C#中对我的数据访问层进行unit testing。 我是主要的Java开发人员,并且只使用了C#大约6个月,过去我使用了一个名为DBUnit的库来测试已知的状态数据库。 我无法找到一个可以使用的类似活动库,最近似乎是nDBUnit但它现在已经有一段时间没有活动了。

关于C#中的方式和原因似乎存在很多相互矛盾的方法。 理想情况下,我想使用模拟测试数据访问层,而无需连接到数据库,然后在一组单独的测试中对存储过程进行unit testing。

在我正在研究的系统中,数据访问层是使用ADO.net(不使用entity framework)在SQL Server上调用存储过程。

以下是我必须使用的示例代码; 沿着模拟路径,我必须能够模拟SqlCommand(使用IDbCommand)和/或模拟SqlConnection。

所以我的问题是什么似乎是最好的方式(如果有这样的事情)这样做? 到目前为止,唯一的方法是使代理对象传递给构造函数,以便它可以返回模拟的Sql *对象进行测试。

我还没有机会查看所有可用的C#模拟库。

public class CustomerRepository : ICustomerRepository { private string connectionString; public CustomerRepository (string connectionString) { this.connectionString = connectionString; } public int Create(Customer customer) { SqlParameter paramOutId = new SqlParameter("@out_id", SqlDbType.Int); paramOutId.Direction = ParameterDirection.Output; List sqlParams = new List() { paramOutId, new SqlParameter("@name", customer.Name) } SqlConnection connection = GetConnection(); try { SqlCommand command = new SqlCommand("store_proc_name", connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.AddRange(sqlParams.ToArray()); int results = command.ExecuteNonQuery(); return (int) paramOutId.Value; } finally { CloseConnection(connection); } } } 

遗憾的是,您无法找到将数据库置于已知状态的工具,并允许您针对数据库运行CustomerRepository以测试CustomerRepository。 但是,答案不是开始使用模拟来模拟所有ADO调用。 通过这样做,您最终创建了一个unit testing,它并没有真正测试任何逻辑:它只是测试代码的编写方式是您认为应该编写的。

假设我最终编写了一个SQL INSERT作为我在SQL数据库中创建客户的命令。 现在让我们说我们正在进行更改,以便customer表具有不同的字段(这会破坏我们的INSERT命令),现在我们应该使用存储过程来创建客户。 使用模拟的测试仍然会通过,即使它正在测试的实现现在已被破坏。 此外,如果您将实现修复为使用存储过程,则unit testing现在将失败。 如果unit testing在失败时继续通过但在修复系统时失败则有什么意义呢?

有关可能的替代方案,请参阅此问题 看起来标记的答案实际上是使用IKVM在C#中最终使用DBUnit。

因此,可能还有其他途径可以继续探索,但嘲笑ADO调用只会导致脆弱的测试,而不是真正测试任何重要的东西。

该层的工作是将代码连接到数据库。 它必须封装有关db连接和语法的知识。 通常将域语言映射到数据库语言。 我将unit testing的这一部分看作集成测试,因此我测试数据库模式是否与实际或测试数据库等效。 有关此主题的更多信息 。

我从获得IDbConnection开始,然后您基本上可以从中完成其余的代码。

 using(IDbConnection conn = factory.GetConnection(connectionstring)) { conn.Open(); using(IDbTransaction trans = conn.BeginTransaction()) { IDbCommand command = conn.CreateCommand(); IDataParameter param = command.CreateParameter(); // Do something with your command trans.Commit(); } } 

然后,您可以模拟工厂,IDbConnection,IDBTransaction以及从中创建的任何其他ADO对象。 至于模拟库,我使用Moq

要测试DataAccess Layer,您需要一个更复杂的结构。

DataAccess Layer将调用Repository对象的引用。 Repo对象将通过UnitOfWork设计模式调用Entity Framework DbSets中的引用。

数据访问层(TOP)
|
的UnitOfWork
|
存储库模式类
|
EF语境
|
实际数据库

设置结构后,您将模拟存储库类。 例如,项目将被插入到DB而不是模拟对象。 稍后您将断言您的模拟对象以查看是否插入了项目。

请查看实现存储库和工作单元模式