简体   繁体   English

模拟IOrganizationService(Dynamics CRM)时未过滤LINQ查询结果

[英]LINQ query results not filtered when mocking IOrganizationService (Dynamics CRM)

I am having a problem unit testing my code that queries Dynamics CRM 2015. 我在测试查询Dynamics CRM 2015的代码时遇到问题单元。

I use the Moq framework and mock the IOrganizationService as follows: 我使用Moq框架并模拟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);

So, the IOrganizationService mock would always return the same predefined list of accounts, no matter what the request is like. 因此,无论请求是什么样的, IOrganizationService模拟都将始终返回相同的预定义帐户列表。

This is the code I am trying to test: 这是我要测试的代码:

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

When this code is executed against a real CRM instance, it works as expected. 当针对真正的CRM实例执行此代码时,它将按预期工作。

Using a mocked IOrganizationService , the code does not work anymore. 使用IOrganizationService ,代码不再起作用。 In the debugger, I can see that AccountSet returns the expected account list (the one I set up during mocking). 在调试器中,我可以看到AccountSet返回预期的帐户列表(我在模拟过程中设置的帐户列表)。 However, the Where method does not seem to get executed, and query contains all the account entities. 但是, Where方法似乎没有执行,并且query包含所有帐户实体。 So, the call to FirstOrDefault returns only the first one, and not the result of calling the Where method. 因此,对FirstOrDefault的调用FirstOrDefault返回第一个, FirstOrDefault返回调用Where方法的结果。

If I modify the code as follows, it also starts working during unit testing: 如果我按以下方式修改代码,则它也将在单元测试期间开始工作:

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

If I understand correctly, this code retrieves all the accounts, and filters them locally (not in CRM). 如果我理解正确,那么此代码将检索所有帐户,并在本地进行过滤(不在CRM中)。 This is fine for unit testing, but this would not be acceptable in the real application. 这对于单元测试很好,但是在实际应用中是不可接受的。

Could anyone please advise what I am doing wrong? 谁能告诉我我在做什么错? Thank you! 谢谢!

Edit : 编辑

We ended up mocking serviceContext instead because we call methods (or properties) on it directly from the client code, and not the ones on IOrganizationService . 我们最终模拟了serviceContext因为我们直接从客户端代码而不是IOrganizationService上调用方法(或属性)。 I think that mocking IOrganizationService should only make sense if the code we want to test uses IOrganizationService directly and not via serviceContext . 我认为IOrganizationService仅在我们要测试的代码直接使用IOrganizationService而不是通过serviceContext使用IOrganizationService Otherwise, we have something like two-level mocking, and it becomes messy. 否则,我们会有类似两层模拟的东西,并且会变得混乱。

Please give a try to FakeXrmEasy . 请尝试FakeXrmEasy There are some introduction videos and many different testing examples. 有一些介绍视频和许多不同的测试示例。

By using FakeXrmEasy mocks are already handled by the framework, therefore reducing the amount of boilerplate code just to setup your test. 通过使用FakeXrmEasy,框架已经处理了模拟,因此减少了用于设置测试的样板代码的数量。

I've been working on it since 2014, and it is MIT licensed. 自2014年以来,我一直在研究它,并且它是MIT许可的。 Actually, if anyone would like to contribute to the project it would be super awesome! 实际上,如果有人愿意为该项目做贡献,那就太好了! :) :)

EDIT : Just adding a link to a blog post which compares FakeXrmEasy against other .NET mocking frameworks. 编辑 :只需将链接添加到博客文章中,即可将FakeXrmEasy与其他.NET模拟框架进行比较。 The purpose is nothing but to be able to have as many work done for Dynamics CRM as possible. 目的只是为了能够为Dynamics CRM完成尽可能多的工作。 With other .NET mocking frameworks there is basically too much to mock, every single time. 与其他.NET模拟框架相比,基本上每次都有太多模拟对象。

The Where clause becomes a part of the query executed against the OrganizationService which in your case is mocked to always return the full accounts list regardless of conditions. Where子句成为针对OrganizationService执行的查询的一部分,在这种情况下,无论条件如何,该子句都会被模拟为始终返回完整的accounts列表。 You could add more logic to your moq, but generally that's not necessary in unit tests as your goal is to test your business logic and not your ability to mock the OrganizationService . 您可以在最小起订量中添加更多逻辑,但是通常在单元测试中没有必要,因为您的目标是测试业务逻辑,而不是模拟OrganizationService能力。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 适用于Microsoft Dynamics CRM的IOrganizationService的单个实例 - Single instance of IOrganizationService for microsoft dynamics crm LINQ to Dynamics CRM查询优化 - LINQ to Dynamics CRM query optimisation LINQ to Dynamics CRM查询本地过滤记录 - LINQ to Dynamics CRM Query filtering records locally 在Dynamics CRM 2011 Linq查询中进行双重订购 - double order by in Dynamics CRM 2011 Linq query CRM Dynamics - 从FaultException获取服务uri <OrganizationServiceFault> 或IOrganizationService - CRM Dynamics - Get service uri from FaultException<OrganizationServiceFault> or IOrganizationService 是否可以通过带有 IOrganizationService 的 WebApi 使用 JSON 请求调用 Dynamics CRM 操作? - Is it possible to call an Dynamics CRM action with a JSON request through a WebApi with IOrganizationService? 在CRM 2011插件中模拟IOrganizationService.Execute的问题 - Issue with mocking IOrganizationService.Execute in CRM 2011 plugin Dynamics CRM-查询取消并接收部分结果 - Dynamics CRM - query cancellation and receive partial results Linq加入以针对Dynamics CRM 2015执行特定查询 - Linq join to perform specific query against Dynamics CRM 2015 如何在Dynamics CRM 2011中查询(使用LINQ)FormattedValues - How to query (using LINQ) FormattedValues in Dynamics CRM 2011
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM