C# 数据访问层单元测试方法
我一直在寻找一种有效的方法,用C#对我的数据访问层进行单元测试。我主要是一名Java开发人员,只使用C#大约6个月,过去我使用了一个名为DBUnit的库来测试已知的状态数据库。我还没有找到一个类似的活动库可以使用,最近的似乎是nDBUnit,但它已经有一段时间没有活动了 在C#中,似乎有很多相互矛盾的方法来解释如何和为什么使用C#。理想情况下,我希望使用模拟来测试数据访问层,而不需要连接到数据库,然后在一组单独的测试中对存储过程进行单元测试 在我正在研究的系统中,数据访问层使用ADO.net(不使用实体框架)在SQL Server上调用存储过程 下面是我必须使用的示例代码;要继续模拟路径,我必须能够模拟SqlCommand(使用IDbCommand)和/或模拟SqlConnection 所以我的问题是什么似乎是最好的方式(如果有这样的事情)来做到这一点?到目前为止,唯一的方法是生成传递到构造函数中的代理对象,以便它可以返回模拟的Sql*对象进行测试 我还没有机会查看所有可用的C#mock库C# 数据访问层单元测试方法,c#,unit-testing,testing,persistence,data-access-layer,C#,Unit Testing,Testing,Persistence,Data Access Layer,我一直在寻找一种有效的方法,用C#对我的数据访问层进行单元测试。我主要是一名Java开发人员,只使用C#大约6个月,过去我使用了一个名为DBUnit的库来测试已知的状态数据库。我还没有找到一个类似的活动库可以使用,最近的似乎是nDBUnit,但它已经有一段时间没有活动了 在C#中,似乎有很多相互矛盾的方法来解释如何和为什么使用C#。理想情况下,我希望使用模拟来测试数据访问层,而不需要连接到数据库,然后在一组单独的测试中对存储过程进行单元测试 在我正在研究的系统中,数据访问层使用ADO.net(不
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);
}
}
}
公共类CustomerRepository:ICCustomerRepository
{
私有字符串连接字符串;
公共CustomerRepository(字符串连接字符串)
{
this.connectionString=connectionString;
}
公共int创建(客户)
{
SqlParameter paramOutId=新的SqlParameter(“@out\u id”,SqlDbType.Int);
paramOutId.Direction=ParameterDirection.Output;
List sqlParams=新列表()
{
paramOutId,
新的SqlParameter(“@name”,customer.name)
}
SqlConnection=GetConnection();
尝试
{
SqlCommand=newsqlcommand(“store\u proc\u name”,connection);
command.CommandType=CommandType.storedProcess;
AddRange(sqlParams.ToArray());
int results=command.ExecuteNonQuery();
返回(int)paramOutId.Value;
}
最后
{
闭合连接(连接);
}
}
}
此层的任务是将代码连接到数据库。它必须封装有关db连接和语法的知识。在中,通常将域语言映射到数据库语言。我将这部分单元测试视为集成测试,因此,我测试数据库模式是否与真实或测试数据库等效。有关此主题的更多信息。不幸的是,您找不到一个工具,可以将数据库置于已知状态,并让您针对数据库运行CustomerRepository以测试CustomerRepository。但是,答案不是开始使用mock模拟所有ADO调用。通过这样做,您最终创建了一个单元测试,它并不真正测试任何逻辑:它只是测试代码是否按照您认为应该的方式编写
假设我最后编写了一个SQL插入,作为在SQL数据库中创建客户的命令。现在让我们假设我们正在进行更改,以便customer表具有不同的字段(这会中断INSERT命令),现在我们应该使用存储过程来创建customer。使用mock的测试仍然会通过,即使它所测试的实现现在已经中断。此外,如果您修复了使用存储过程的实现,那么单元测试现在将失败。如果单元测试在应该失败时仍然通过,但在修复系统时又会失败,那么单元测试的意义何在
请参阅以了解一些可能的替代方案。看起来有标记的答案是,实际上只是在C#中使用DBUnit,然后使用IKVM
因此,可能有其他途径可以继续探索,但模拟ADO调用只会导致脆弱的测试,而这些测试并不真正测试任何重要的内容。要测试DataAccess层,您需要更复杂的结构 DataAccess层将调用来自存储库对象的引用。 Repo对象将通过UnitOfWork设计模式从实体框架数据库集调用引用 数据访问层(顶部)
|
工作单元
|
存储库模式类
|
EF上下文
|
实际数据库 设置结构后,将模拟存储库类。例如,项将被插入到DB中,而将转到模拟对象。稍后,您将针对模拟对象断言是否插入了项
请看一看谢谢,我在周末对此进行了更好的研究,我同意测试应该访问一个真实的数据库,我们的Java项目就是这样工作的,尤其是随着项目的增长,表和列名发生了变化。我看了一下IKM方法,我不想引入太复杂的东西,让其他开发人员无法管理和理解。这就是为什么您应该创建一个使用存储库/DAL的服务。您模拟存储库,将其注入服务并测试该服务。然后,您将单独测试服务中的逻辑。如果存储库中断(返回不正确的数据),逻辑将失败,测试将失败。看到人们嘲笑一个存储库,然后断言从该存储库返回总是很有趣的。谢谢,我想我对这件事看得太多了,我本来想这么做,但由于c#中缺少这样的库,我开始寻找替代方案。