我有一個存儲庫,公開IQueryable和一個服務處理特定的查詢,這裏有幾個使用DbFunctions的方法。爲了可以測試,我使用靜態元素列表創建一個虛假的存儲庫並將其注入到服務中。問題是,由於我的服務查詢列表,並沒有使用數據庫,我得到錯誤「此功能只能從LINQ到實體調用。」。單元測試SqlFunctions
有沒有比測試DbFunctions和QueryProvider更簡單的測試方法?
在此先感謝
我有一個存儲庫,公開IQueryable和一個服務處理特定的查詢,這裏有幾個使用DbFunctions的方法。爲了可以測試,我使用靜態元素列表創建一個虛假的存儲庫並將其注入到服務中。問題是,由於我的服務查詢列表,並沒有使用數據庫,我得到錯誤「此功能只能從LINQ到實體調用。」。單元測試SqlFunctions
有沒有比測試DbFunctions和QueryProvider更簡單的測試方法?
在此先感謝
你不能可靠地假冒SQL歸因於LINQ對象在許多情況下比LINQ to SQL的行爲不同的事實。例如,其中(new [] { "asdf"}).Contains("ASDF")
在LINQ中將對象返回爲false,則LINQ to SQL中相同類型的查詢將返回true。我發現的最好的事情是將數據的檢索與數據的操作分開。也許創建一種將IPersonRepository作爲依賴關係的PersonManager。您可以僞造/模擬IPersonRepository並使用它來測試PersonManager在各種情況下執行它應該執行的操作。
嗨,亞歷克斯,謝謝你的回覆。 我剛剛發現有人在這裏有同樣的問題:http://stackoverflow.com/questions/14883360/how-to-unit-test-getnewvalues-which-contains-entityfunctions-adddays-function 你給的例子可以如果您在EntityFunctionsFake類上創建一個具有相同簽名的Contains方法,並在比較時指定IgnoreCase,則可以使用給定的解決方案來解決該問題。它可能不適合所有情況,但至少我現在可以測試我的要求。你怎麼看? 乾杯 –
儘管您不能在LINQ查詢中使用IgnoreCase。 –
,因爲我最近打了同樣的問題,而採用一個簡單的解決方案,希望它張貼在這裏..這個解決方案不需要墊片,嘲諷,沒有什麼膨脹等
這樣,您的單元測試將檢查您的方法的幾乎95%與現場代碼的奇偶校驗。你仍然有「DbFunctions」與你等價的代碼的差異,但要勤於此,95%看起來會有很大的收益。
public SomeMethodWithDbFunctions(bool useDbFunctions = true)
{
var queryable = db.Employees.Where(e=>e.Id==1); // without the DbFunctions
if (useDbFunctions) // use the DbFunctions
{
queryable = queryable.Where(e=>
DbFunctions.AddSeconds(e.LoginTime, 3600) <= DateTime.Now);
}
else
{
// do db-functions equivalent here using C# logic
// this is what the unit test path will invoke
queryable = queryable.Where(e=>e.LoginTime.AddSeconds(3600) < DateTime.Now);
}
var query = queryable.Select(); // do projections, sorting etc.
}
單元測試將調用方法爲:
SomeMethodWithDbFunctions(useDbFunctions: false);
因爲單元測試將必須設置本地的DbContext實體,C#的邏輯/日期時間的功能是可行的。
我試圖執行DateDiff函數,和它的作品對我來說 但我們應該認爲,在這種情況下,我們測試不同的功能 ,我們在LINQ代碼測試不實的行爲
private class MySqlFunctions
{
[DbFunction("SqlServer", "DATEDIFF")]//EF will use this function
public int? DateDiff(string datePartArg, DateTime startDate, DateTime endDate)
{
var subtract = startDate.Subtract(endDate);
switch (datePartArg)
{
case "d":
return (int?)subtract.TotalDays;
case "s":
return (int?)subtract.TotalSeconds; // unit test will use this one
}
throw new NotSupportedException("Method supports only s or d param");
}
}
然後
var sqlFunctions = new TpSqlFunctions();
var result = matches.Average(s => sqlFunctions.DateDiff("s", s.MatchCreated, s.WaitingStarted);
這隻會[許多需要替換的酮](http://stackoverflow.com/questions/13332002/how-to-mock-the-limitations-of-entityframeworks-implementation-of-iqueryable/ 13352779#13352779)。做集成測試。模擬將永遠不可靠或需要太多的代碼(+維護),以致它們自己成爲應用程序。你需要爲你的單元測試框架進行單元測試! –
謝謝格特!嘲笑DbFunctions確實很困難,我已經能夠做出一些我需要的東西,但正如你所說,這只是維護。 –