2011-06-16 122 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; 
     //*************************************************// 

希望这有助于

相关问题