[英]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.