2016-05-31 65 views
1

我想寫單元測試執行一個oracle查詢來過濾內存中的對象列表。如何模擬執行oracle查詢到內存中的數據

我該如何模擬,以便篩選條件將應用於我的內存列表中的對象而不是實際的數據庫?

我可以通過實體框架來實現這一點,我可以模擬上下文並返回內存數據,但不知道如何使用OracleCommand.ExecuteReader實現相同。

using (var connection = new OracleConnection(connectionString)) 
{ 
    connection.Open(); 

    var cmd = new OracleCommand 
     { 
      //TODO add Reg_Date in Where clause 
      Connection = connection, 
      CommandText = 
       "SELECT mi.* from fromTable mi where 1=1 " 
       + (string.IsNullOrEmpty(nuf) ? "" : " and mi.NUF != '"+ nuf +"'") 
       + " and mi.Category<>'TES' and mi.Category<>'CVD'" 
      CommandType = CommandType.Text 
     }; 

    Debug.WriteLine(cmd.CommandText); 

    var dr = cmd.ExecuteReader(); 
} 
+0

所以當你執行cmd時,你得到了什麼或者沒有得到什麼。也嘗試構建您的查詢要麼調用存儲過程,但儘量不要使用連接字符串來建立查詢..你正在設置自己的SQL注入。 – MethodMan

+0

當然。稍後,我將從內聯SQL轉移到存儲過程。這可以查詢實際的數據庫。我想查詢內存中的數據並應用過濾器,以便我可以進行單元測試。 –

+0

嘗試將數據作爲DataTable返回,並使用DataTables'Filer'函數。所以你可以查詢..有大量的工作例子,如何做到這一點以及在StackOverflow以及互聯網,如果你做一個'谷歌搜索在C#Stackoverflow DataTable.Filter'它會產生很多結果。 – MethodMan

回答

2

當前被測方法與實現方面的問題緊密耦合,使得單元可以很容易地單獨測試。嘗試將這些實現問題抽象出來,以便它們可以輕鬆地進行孤立測試。

public interface IDbConnectionFactory { 
    IDbConnection CreateConnection(); 
} 

上述連接工廠的抽象可用於訪問您的Oracle數據存儲的其他必要System.Data抽象。

public class MyDataAccessClass { 
    private IDbConnectionFactory connectionFactory; 

    public MyDataAccessClass(IDbConnectionFactory connectionFactory) { 
     this.connectionFactory = connectionFactory; 
    } 

    public object GetData(string nuf) { 
     using (var connection = connectionFactory.CreateConnection()) { 
      connection.Open(); 
      var query = "SELECT mi.* from fromTable mi where 1=1 " 
         + (string.IsNullOrEmpty(nuf) ? "" : " and mi.NUF != @nuf") 
         + " and mi.Category<>'TES' and mi.Category<>'CVD'" 
      using(var command = connection.CreateCommand()){ 
       command.CommandText = query; 
       command.CommandType = CommandType.Text; 
       if(!string.IsNullOrEmpty(nuf)) { 
        var parameter = command.CreateParameter(); 
        parameter.ParameterName = "@nuf"; 
        parameter.Value = nuf; 

        command.Parameters.Add(parameter); 
       } 

       Debug.WriteLine(command.CommandText); 

       var dr = command.ExecuteReader(); 

       //...other code removed for brevity 
      } 
     } 
    } 
} 

的生產實施工廠將返回的實際OracleConnection

public class OracleConnectionFactory: IDbConnectionFactory { 
    public IDbConnection CreateConnection() { 
     return new OracleConnection("connection string"); 
    } 
} 

其可以通過依賴注入被傳遞到從屬類。

爲了測試你使用你選擇的模擬框架來模擬接口,或者創建自己的假貨來注入和測試你的方法。

[TestClass] 
public class DataAccessLayerUnitTest { 
    [TestMethod] 
    public void TestFilter() { 
     //Arrange 
     var readerMock = new Mock<IDataReader>(); 

     var commandMock = new Mock<IDbCommand>(); 
     commandMock.Setup(m => m.ExecuteReader()) 
      .Returns(readerMock.Object) 
      .Verifiable(); 

     var parameterMock = new Mock<IDbDataParameter>();    

     commandMock.Setup(m => m.CreateParameter()) 
      .Returns(parameterMock.Object); 

     commandMock.Setup(m => m.Parameters.Add(It.IsAny<IDbDataParameter>())) 
      .Verifiable(); 

     var connectionMock = new Mock<IDbConnection>(); 
     connectionMock 
      .Setup(m => m.CreateCommand()) 
      .Returns(commandMock.Object); 

     var connectionFactoryMock = new Mock<IDbConnectionFactory>(); 
     connectionFactoryMock 
      .Setup(m => m.CreateConnection()) 
      .Returns(connectionMock.Object); 

     var sut = new MyDataAccessClass(connectionFactoryMock.Object); 
     var input = "some value"; 

     //Act 
     var data = sut.GetData(input); 

     //Assert 
     commandMock.Verify(); 
    } 
} 

最後,您使用的命令參數的命令文本與外在價值手動構建查詢字符串建議打開代碼最多SQL注入攻擊。

+0

這聽起來不錯,但是如果'CreateConnection()'必須返回一個mockableÌDbConnection'(這是練習的全部重點),它可以**不返回** OracleConnection **。這種想法使整個想法變得不可行,這是一種恥辱。 – oerkelens

+0

@ oerkelens你指的是什麼? 'OracleConnection'是從'IDbConnection'派生的一個實現問題。我想你在誤解這裏的概念。澄清你有什麼擔憂。 – Nkosi

+0

我盯着定義DbConnection和IDbConnection,沒有意識到它們已經存在,並且OrackeConnection實現了System.Data.DbConnection。現在感覺很蠢......並且很高興地繼續解決你的問題! – oerkelens