2016-06-20 119 views
1

我有一個問題,單元測試我的代碼,查詢動態CRM 2015年LINQ查詢結果不過濾嘲諷IOrganizationService(動態CRM)時

我使用起訂量框架和嘲弄IOrganizationService如下:

IList<Account> accounts = new List<Account> {/*...*/}; 
IList<IEntity> expected = new List<Entity>(accounts); 
var collection = new EntityCollection(expected); 
var retrieveMultipleResponse = new RetrieveMultipleResponse 
{ 
    Results = new ParameterCollection 
    { 
     { "EntityCollection", collection} 
    } 
}; 
var mockOrganizationService = new Mock<IOrganizationService>(); 
mockOrganizationService.Setup(os => os.Execute(
    It.IsAny<RetrieveMultipleRequest>())).Returns(retrieveMultipleResponse); 

因此,IOrganizationService模擬將始終返回相同的預定義帳戶列表,無論請求是什麼樣子。

這是我想測試代碼:

var query = serviceContext.AccountSet.Where(
       a => a.AccountId != null && a.AccountId.Value == guid) 
var account = query.FirstOrDefault(); 

當對一個真正的CRM實例執行這段代碼,它按預期工作。使用模擬的IOrganizationService,代碼不再工作。在調試器中,我可以看到AccountSet返回預期的帳戶列表(我在模擬期間設置的那個)。但是,Where方法似乎不會執行,並且query包含所有帳戶實體。因此,對FirstOrDefault的調用只返回第一個,而不是調用Where方法的結果。

如果我修改代碼如下,它也開始在單元測試過程的工作:

var query = serviceContext.AccountSet.ToList().Where(
        a => a.AccountId != null && a.AccountId.Value == guid) 
var account = query.FirstOrDefault(); 

如果我理解正確的話,這個代碼檢索所有帳戶,並篩選它們在本地(而不是在CRM)。這對單元測試很好,但在實際應用中這是不可接受的。

任何人都可以請告知我做錯了什麼?謝謝!

編輯

我們結束了直接從客戶端代碼就可以了嘲諷serviceContext而不是因爲我們調用的方法(或屬性),而不是IOrganizationService的人。我認爲如果我們想要測試的代碼直接使用IOrganizationService而不是通過serviceContext,那麼嘲笑IOrganizationService應該是有意義的。否則,我們有兩層嘲弄的東西,它變得凌亂。

+0

你是對的。在ToList()語句之後,所有的行都被檢索出來,並且你正在使用Linq To Objects來過濾這些項目。 CRM linq提供者的實現是錯誤的並且不完整。永遠不要指望使用moq總是會給出與「真正」實現相同的結果。 –

+0

顯示更多關於您正在嘗試測試的代碼的詳細信息,因爲它涉及到'serviceContext.AccountSet',因此[mcve]將允許更好地複製您的問題 – Nkosi

+0

@JeroenHeier,這就是許多原因之一我開始了[FakeXrmEasy](http://dynamicsvalue.com/get-started/overview)。這個自動模擬框架將爲您提供更真實的「真實」組織服務的行爲體驗......並且根本不使用任何模擬遊戲! :) – Jordi

回答

0

Where子句成爲針對OrganizationService執行的查詢的一部分,在您的情況下,該查詢會被模擬爲始終返回完整的accounts列表,而與條件無關。您可以爲moq添加更多邏輯,但通常在單元測試中這不是必需的,因爲您的目標是測試業務邏輯,而不是模擬OrganizationService的能力。

+0

嗨馬特,請記住,任何業務邏輯的重要組成部分都是查詢......有很多連接和過濾器......例如:當您使用許多插件或代碼活動時,需要執行查詢來檢索X記錄對它們執行X操作,那麼基本上每個查詢都需要一個模擬對象,因爲在每種情況下都需要返回不同的實體列表。 – Jordi

+0

@Jordi我同意這些查詢是非常重要的,但他們只能真正用集成和功能測試與實際數據進行測試,而不是模擬。如果你正在編寫單元測試,你的重點將放在你的業務邏輯上,而不是針對orgservice的CRUD操作。 –

+0

Hi @Matt,你試過FakeXrmEasy嗎?它有一個運行Fetch,QueryByAttribute,LINQ和QueryExpressions的查詢引擎。它的目的是能夠在集成測試之前對這些查詢進行單元測試。 [Here](http://dynamicsvalue.com/blog/fake-xrm-easy-versus-other-frameworks)是一個鏈接,它比較了FakeXrmEasy運行的查詢,而不是其他模擬框架。任何反饋都會比歡迎! :) – Jordi

1

請試試看FakeXrmEasy。有一些介紹視頻和許多不同的測試示例。

通過使用FakeXrmEasy mocks已經由框架處理,因此減少了樣板代碼的數量以設置您的測試。

自2014年以來,我一直致力於此工作,並獲得MIT許可。其實,如果有人願意爲這個項目做出貢獻,那就太棒了! :)

編輯:只是adding a link到一個博客文章比較FakeXrmEasy與其他.NET模擬框架。目的不過是爲了儘可能地爲Dynamics CRM完成儘可能多的工作。使用其他.NET嘲諷框架,每次都嘲笑它太多了。