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

wen*_*nic 17 c# testing persistence unit-testing 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);
     }

   }

}
Run Code Online (Sandbox Code Playgroud)

Mar*_*eth 21

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

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

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

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


小智 3

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