Как издеваться над SqlParameterCollection с помощью Moq

Я пытаюсь издеваться над операциями с базой данных. У меня проблема с насмешкой над SqlParameterCollection. Я попытался создать метод virtual, который вернет DbParameterCollection, но тогда я теряю все функции, которые дает SqlParameterCollection, например AddWithValue и т. д. Есть ли способ, которым я могу издеваться над SqlParameterCollection? Есть ли другой подход к модульному тестированию DAL? Я использую Moq.

Код выглядит следующим образом:

в ДАЛ:

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

В проекте модульного тестирования:

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

--Решение--

Создан метод расширения для добавления параметра со значением. Спасибо, Марк Гравелл, за то, что указали мне в этом направлении.

    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;

    }

person Asdfg    schedule 16.06.2011    source источник
comment
Возможно, вы захотите вызвать .Parameters.Add с вновь созданным параметром, так как это ожидается с помощью метода Add.   -  person Marc Gravell    schedule 16.06.2011


Ответы (3)


Лично я подхожу к этой проблеме, написав метод расширения AddParameterWithValue для DbCommand (или IDbCommand). Это должно быть в команде, чтобы у вас был доступ к CreateParameter, а затем вызовите .Parameters.Add.

Это позволяет легко использовать любой стек ADO.NET, включая абстракции, такие как декораторы ведения журнала.

person Marc Gravell    schedule 16.06.2011
comment
@Asdfg Я думаю, что оставил версию этого щеголя, если вам это нужно - person Marc Gravell; 16.06.2011
comment
Это будет круто. Я пишу метод расширения, но борюсь там. - person Asdfg; 16.06.2011

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

Надеюсь это поможет

person Shaiju Janardhanan    schedule 02.02.2015

Привет, я нашел решение.

Мне пришлось реализовать Moq для интерфейса IDataParameterCollection и отправить его экземпляру IDbCommand.

При этом мой объект IDbCommand.Parameters стал отличаться от нуля.

    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;
    }
person Luã Govinda Mendes Souza    schedule 05.04.2020