2011-06-16 112 views
5

我試圖模擬數據庫操作。我在嘲笑SqlParameterCollection有問題。我試圖創建virtual方法,將返回DbParameterCollection,但然後我失去了SqlParameterCollection給出的所有功能AddWithValue等。有沒有辦法我可以模擬SqlParameterCollection?是否有任何其他方法來單元測試DAL?我正在使用Moq。如何使用Moq模擬SqlParameterCollection

代碼是這樣的:

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

在單元測試項目:

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--

創建一個擴展方法來添加參數與值。謝謝Marc Gravell指示我朝那個方向走。

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; 

    } 
+0

您可能需要調用.Parameters.Add與新創建的參數,因爲這是預期與聽起來很有趣,添加方法 – 2011-06-16 19:08:42

回答

7

個人而言,我通過寫一個AddParameterWithValue擴展方法DbCommand(或IDbCommand)處理這個問題。它必須在命令上,以便您可以訪問CreateParameter,然後致電.Parameters.Add

這允許輕鬆使用任何ADO.NET堆棧,包括抽象如日誌裝飾器。

+0

。 – Asdfg 2011-06-16 18:34:44

+0

@Asdfg我認爲我在「dapper」中留下了這個版本,如果你需要的話 – 2011-06-16 18:44:21

+0

這會很酷。我正在寫擴展方法,但在那裏掙扎。 – Asdfg 2011-06-16 18:49:39

1

@Asdfg HI我已經基本嘲笑參數採集如下

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

希望這有助於

相關問題