单元测试数据访问层的方法

时间:2013-02-21 11:18:53

标签: c# unit-testing testing persistence data-access-layer

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

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

在我正在研究的系统中,数据访问层将使用ADO.net(不使用实体框架)在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<SqlParameter> sqlParams = new List<SqlParameter>()
     {
       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);
     }

   }

}

3 个答案:

答案 0 :(得分:21)

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

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

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

所以,可能还有其他方法可以继续探索,但嘲笑ADO调用只会导致脆弱的测试,而这些测试并没有真正测试任何重要的东西。

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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

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

DataAccess Layer(TOP)
|
的UnitOfWork
|
存储库模式类
|
EF背景
|
实际数据库

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

请查看Implementing the Repository and Unit of Work Patterns