开发者

How to mock SqlParameterCollection using Moq

开发者 https://www.devze.com 2023-03-13 23:00 出处:网络
I am trying to mock database operations. I have problem in mocking SqlParameterCollection. I tried to create virtual method that will return DbParameterCollection but then i am loosing all the functio

I am trying to mock database operations. I have problem in mocking SqlParameterCollection. I tried to create virtual method that will return DbParameterCollection but then i am loosing all the functionality that SqlParameterCollection gives like AddWithValue etc. Is there a way i can mock SqlParameterCollection? Is there any other approach to unit test DAL? I am using Moq.

Code goes like this:

in DAL:

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();
           }
     }
}

In Unit test project:

    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());
    }

--Solution--

Created an extension method to add parameter with value. Thank you Marc Gravell for pointing me to that direction.

    public static IDbDataParameter AddParameterWithValue(this IDbCommand cmd, string paramName, object paramValue)
    {

        var dbParam = cmd.CreateParameter();
        if (dbParam != null)
        {
            dbParam.ParameterName = paramName;
            dbParam.Value = paramValue;
        }
        return dbParam;

    }


Personally, I approach this problem by writing an AddParameterWithValue extension method to DbCommand (or IDbCommand). It has to be on the command so that you have access to CreateParameter, and then call .Parameters.Add.

This allows easy usage against any ADO.NET stack, including abstractions like logging decorators.


@Asdfg HI I have basically mocked the parameter collection as below

 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;
        //*************************************************//

Hope this helps


Hi i found the solution.

I had to implement a Moq for the IDataParameterCollection interface and had to send it to the instance of IDbCommand.

With that my IDbCommand.Parameters object became different from 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;
    }
0

精彩评论

暂无评论...
验证码 换一张
取 消