我对单元测试比较陌生,而且对于模拟来说是全新的。我有一个包装DbProvider工厂的数据库类,我想在不连接数据库的情况下创建单元测试。
我如何模仿DbProvider工厂,所以我可以传入它来测试我的课程?我是否还需要模拟DbConnection,DbCommand等?我的代码的一小部分如下:
public Database(DbProviderFactory dbProviderFactory) {
Provider = dbProviderFactory;
}
public int UpdateRecords(string sql, CommandType type, params DbParameter[] parameters) {
int numberOfRecordsUpdated;
using (var connection = CreateConnection()) {
// Add ConnectionString
connection.ConnectionString = ConnectionString;
// Create command to hold the update statment
using (var command = CreateCommand()) {
try {
command.Connection = connection;
command.CommandType = type;
command.CommandText = sql;
// Add Parameters
foreach (var parameter in parameters) {
command.Parameters.Add(parameter);
}
// Open Connection
connection.Open();
// Execute SQL
numberOfRecordsUpdated = command.ExecuteNonQuery();
} finally {
command.Parameters.Clear();
}
}
}
return numberOfRecordsUpdated;
}
答案 0 :(得分:2)
如果您对测试从数据库中获取数据感兴趣(根据您的评论判断),您将执行integration test
。
这些类型的测试与unit testing
的区别在于它们运行频率较低 - 最佳实践要求您在提交源控件之前运行这些测试。
原因是它们速度较慢而且你将会遇到一个真正的数据库(至少是一个测试数据库)。在每次运行中,您将需要擦除数据库或不提交更改 - 您似乎知道您在这里做了什么,所以我将留下您如何处理这个问题。
至于测试使用数据库的逻辑 - mocking
和dependency injection
是可行的方法。
我使用Moq - 它可能是最容易使用的模拟框架。它实际上不仅仅是模拟对象(尽管名称),你可以用它生成stubs and fakes。
伪模拟就像这样(使用数据库示例):
如需进一步的帮助 - 请查看Google - 有一些很好的资源用于单元测试和模拟。
答案 1 :(得分:1)
我个人会模拟包含更高级别数据访问功能的类(如UpdateRecords等),并使用此模拟返回预定的数据集。
使用DbProvider和相应的DbCommand等是数据访问层的实现细节,与使用返回值的更高级别功能无关。
答案 2 :(得分:0)
数据访问类都是关于与DB集成的。例如,Roy Osherove认为这个类在单元测试时是个例外。我也对如何测试这种类型的代码感兴趣。 +1的问题。
以下我不确定模拟数据访问类是否明智。