如何使用Moq模拟SqlParameterCollection

时间:2011-06-16 18:23:55

标签: c# unit-testing moq sqlparameters

我正在尝试模拟数据库操作。我在模仿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());
    }

3 个答案:

答案 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;
    }