我正在尝试模拟数据库操作。我在模仿SqlParameterCollection
时遇到问题。我尝试创建将返回virtual
的{{1}}方法,但之后我将失去DbParameterCollection
提供的所有功能SqlParameterCollection
等。有没有办法可以模拟AddWithValue
1}?单元测试DAL还有其他方法吗?我正在使用Moq。
代码是这样的:
在DAL中:
SqlParameterCollection
在单元测试项目中:
protected virtual IDbConnection GetConnection(string connectionString)
{
return new SqlConnection(connectionString);
}
protected virtual IDbCommand GetCommand(IDbConnection cn)
{
return cn.CreateCommand();
}
protected virtual IDbTransaction GetTransaction(IDbConnection cn)
{
return cn.BeginTransaction(IsolationLevel.Serializable);
}
Public Bool InsertInDatabase(DataTable dt)
{
using (IDbConnection cn = GetConnection(cnstr))
{
cn.Open();
using (IDbTransaction tran = GetTransaction(cn))
{
IDbCommand cmd = GetCommand(cn);
cmd.Transaction = tran;
cmd.Connection = cn;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "sp_InsertInDatabase";
SqlParameterCollection cmdParams = cmd.Parameters as SqlParameterCollection;
cmdParams.AddWithValue("@param1", dt);
cmd.ExecuteNonQuery();
}
}
}
- 解决方案 -
创建了一个扩展方法,用于添加带参数的参数。谢谢Marc Gravell指出我的方向。
protected override IDbConnection GetConnection(string connectionString)
{
return Mock.Of<IDbConnection>();
}
protected override IDbCommand GetCommand(IDbConnection cn)
{
return Mock.Of<IDbCommand>();
}
protected override IDbTransaction GetTransaction(IDbConnection cn)
{
return Mock.Of<IDbTransaction>();
}
public void TestInsertInDatabase()
{
base.InsertInDatabase(new DataTable());
}
答案 0 :(得分:8)
就个人而言,我通过向AddParameterWithValue
(或DbCommand
)编写IDbCommand
扩展方法来解决此问题。必须在命令上,才能访问CreateParameter
,然后拨打.Parameters.Add
。
这允许轻松使用任何ADO.NET堆栈,包括记录装饰器等抽象。
答案 1 :(得分:1)
@Asdfg我基本上嘲笑了参数集合,如下所示
string connectionString = "connectionstring";
var sqlConnection = new SqlConnection(connectionString);
var command = sqlConnection.CreateCommand();
//****************Setup Mock************************//
Castle.DynamicProxy.Generators.AttributesToAvoidReplicating.Add(typeof(System.Data.SqlClient.SqlClientPermissionAttribute));
var mockDataReader1 = new Mock<IDataReader>();
command.Parameters.Add(new SqlParameter("@po_tint_Result", 1));
//setup read return value
Queue<bool> responseQueue = new Queue<bool>();
responseQueue.Enqueue(true);
responseQueue.Enqueue(false);
mockDataReader1.Setup(a => a.Read()).Returns(() => responseQueue.Dequeue());
var mockDb = new Mock<SqlDatabase>(connectionString);
mockDb.Setup(a => a.GetStoredProcCommand("SPNAME")).Returns(command);
mockDb.Setup(a => a.ExecuteNonQuery(command));
obj1.DbConn = mockDb.Object;
//*************************************************//
希望这有帮助
答案 2 :(得分:0)
嗨,我找到了解决方法。
我必须为IDataParameterCollection接口实现Moq,并且必须将其发送到IDbCommand实例。
有了这个,我的IDbCommand.Parameters对象变得不同于null。
public static IDbConnection IDbConnectionMock(int valReturn)
{
var dataParameterCollection = new Mock<IDataParameterCollection>();
var command = new Mock<IDbCommand>();
command.Setup(x => x.Parameters).Returns(dataParameterCollection.Object);
command.Setup(x => x.ExecuteNonQuery()).Returns(valReturn);
var connection = DbConnectionMock_Success(command.Object);
return connection;
}