dynamicsvalue / fake-xrm-easy Goto Github PK
View Code? Open in Web Editor NEWFakeXrmEasy: The Test Automation Framework for the Power Platform / Dataverse
Home Page: https://dynamicsvalue.github.io/fake-xrm-easy-docs/why/
License: Other
FakeXrmEasy: The Test Automation Framework for the Power Platform / Dataverse
Home Page: https://dynamicsvalue.github.io/fake-xrm-easy-docs/why/
License: Other
Hi,
just wanted to make you aware that the Middleware setup fails with the following exception when using FakeItEasy 7.
System.EntryPointNotFoundException
Entry point was not found.
at FakeItEasy.Configuration.ICallbackConfiguration`1.Invokes(Action`1 action)
at FakeItEasy.CallbackConfigurationExtensions.Invokes[TInterface,T1](ICallbackConfiguration`1 configuration, Action`1 actionToInvoke) in C:\projects\fakeiteasy\src\FakeItEasy\CallbackConfigurationExtensions.StronglyTyped.cs:line 31
at FakeXrmEasy.Middleware.Crud.MiddlewareBuilderCrudExtensions.AddFakeUpdate(IXrmFakedContext context, IOrganizationService service)
at FakeXrmEasy.Middleware.Crud.MiddlewareBuilderCrudExtensions.<>c.<AddCrud>b__1_0(IXrmFakedContext context)
at FakeXrmEasy.Middleware.MiddlewareBuilder.Add(Action`1 addToContextAction)
at FakeXrmEasy.Middleware.Crud.MiddlewareBuilderCrudExtensions.AddCrud(IMiddlewareBuilder builder)
In the dependencies of your package the range is listed as FakeItEasy ≥ 6.0.0
which basically allows FakeItEasy 7. Maybe you should update this range to prevent people from having the same troubles as myself.
Let me know if you need any more details. Thanks in advance!
When deleting a record all associated entity references (lookups) pointing to that record should be set to null.
Ideally also implement this logic based on cascade rules.
Link to PR suggested in v1.x: jordimontana82/fake-xrm-easy#561
ILogger interface can be used to log traces to AppInsights:
Hello @jordimontana82 ,
I have been "struggling" a little with building all the packages, and I think I found the issue 😄 basically the powershell scripts need to have "all"
as a default value for $targetFrameworks
so that it produces all the packages with all the necessary frameworks when building it locally.
fake-xrm-easy/build-configuration.ps1
Line 2 in b4ac22c
Line 2 in b4ac22c
fake-xrm-easy/pack-configuration.ps1
Line 3 in b4ac22c
Line 3 in b4ac22c
fake-xrm-easy/build-push-local.ps1
Line 3 in b4ac22c
I'm trying to build the project(s) using the instructions in Readme.md.
I have cloned all of the 2x-dev repos to a folder structure like this:
I have all of the prerequisites installed.
When I run any of the build scripts (eg ./build.ps1 -targetFrameworks all) I get a slew of errors, but the first is this:
C:\Program Files\dotnet\sdk\6.0.101\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(267,5): error NETSDK1005: Assets file 'C:\DynamicsValue\fake-xrm-easy\src\FakeXrmEasy\obj\project.assets.json' doesn't have a target for 'net452'. Ensure that restore has run and that you have included 'net452' in the TargetFrameworks for your project. [C:\DynamicsValue\fake-xrm-easy\src\FakeXrmEasy\FakeXrmEasy.csproj]
Not sure if I'm doing something wrong?
When you build a fetchXml query using the toolbox fetchXml builder which uses the in or not-in operator, it leaves a little bit of redundant fluff in the query:
When you run an early bound query with a condition like this, CRM does not complain and just ignores the value='' bit.
When you run it in fake-xrm-easy (v9 v2 and v3) you get this exception:
System.Exception: When trying to parse value for entity van_technician and attribute statuscode: Integer value expected
I know it's a simple one to avoid, but I think it's worth raising because it took me quite a while to work out that the problem wasn't with the real integer values in the value tag, but the unnecessary value='' attribute in the condition node, so this might trip other people up as well. I couldn't see what was wrong with the query because I was looking in the wrong place, but anyway, it's a valid query as far as CRM is concerned!
I'll also raise an issue in the FXB repo.
It would be great if the library would support working with the interface IOrganizationServiceAsync (https://github.com/microsoft/PowerPlatform-DataverseServiceClient/blob/ba545dcbec78d82dc1aa180b40eaee939978761e/src/GeneralTools/DataverseClient/Client/Interfaces/IOrganizationServiceAsync.cs). Do you have anу plans for it?
This will allow to debug locally the code of plugins but using a connection to a real target environment.
When querying a Money attribute, this query is valid against a real CRM instance:
Against FXE (v2/v9) it gives this error:
The binary operator Equal is not defined for the types 'System.Decimal' and 'System.Int32'.
Easy to fix in code by changing to
query.Criteria.AddCondition("priceperunit", ConditionOperator.Equal, 1.0m);
but just pointing out difference between 'real' behaviour and FXE behaviour.
Sorry if its already reported.
i.e.
new OrganizationRequest()
{
RequestName = "Create",
Parameters = new ParameterCollection
{
{ "Target", new Entity() }
}
}
Should be treated like the current
new CreateRequest()
{
Target = new Entity()
}
Copied from v1: jordimontana82/fake-xrm-easy#467
Queries against MultiSelect OptionSet which use the ContainValues and DoesNotContainValues operators fail with a 'Object reference not set to an instance of an object' exception.
Here are some unit tests, all of which should pass, but do not:
Issue467.zip
If you have a query with a filter which contains conditions affecting both the main query entity and a link entity it fails.
In SQL this would be something like this:
SELECT c.firstname, a.name
FROM contact c
, account a
where c.accountid = a.accountid
and (c.firstname like 'A%' or a.name like 'A%')
This can be written in fetchXML like this:
<fetch top='50'>
<entity name='contact'>
<attribute name='firstname' />
<filter type='or'>
<condition attribute='firstname' operator='begins-with' value='A' />
<condition entityname='account' attribute='name' operator='begins-with' value='A' />
</filter>
<link-entity name='account' from='accountid' to='parentcustomerid' link-type='inner' alias='account'>
<attribute name='name' />
</link-entity>
</entity>
</fetch>
This is a valid query and returns a resultset, as seen here:
Using FakeXrmEasy (v2) gives an 'Object reference not set to an instance of an object.' error.
This is true with either an and or an or filter.
Comment out this line:
<condition entityname='account' attribute='name' operator='begins-with' value='A' />
and the query runs OK, so it seems to be something to do with the aliased link-entity in the filter.
I will upload a failing test once I've submitted the issue.
Scenario is a custom API plugin, and a further plugin registered PostOperation Async on the same message.
I've been able to test the API plugin by setting up a FakeMessageExecutor on the relevant message in which I set up a plugin context and call the plugin. When I run the calling code to send this message, the APIU plugin gets executed correctly.
If I set up Plugin Registration for the postop plugin though, I can still test the main plugin by this method but the later registration is not called.
I think the issue is at https://github.com/DynamicsValue/fake-xrm-easy-plugins/blob/08b7a3f36d9fd10bd941b52224f96bb9f2a6e865/src/FakeXrmEasy.Plugins/IXrmFakedContextPipelineExtensions.cs#L191-L198 where the downstream plugin is only called if target is an Entity
or EntityReference
.
Even if I were to fakeup a Target in my FakeMessageExecutor, the UsePipelineSimulation
code always calls IXrmFakedContextPipelineExtensions.GetTargetForRequest(request)
, and that method (for obvious reasons I guess) only handles built-in messages.
When I have thought it through a bit more will be happy to offer a PR, if you think this is the right track.
For example, the only possible image to register for Create message is a Post-Image in the Post Operation step...
This has been already implemented when finding out if images are available in pipeline execution but is not implemented when registering images (PreImageTests and PostImageTests).
By throwing exceptions during the registration step we're bringing those issues earlier to the moment when they should be addressed.
I've upgraded Microsoft.PowerPlatform.Dataverse.Client to version 0.6.1 and my unit tests are breaking with the error below.
I honestly haven't spent any time looking into whether the issue is caused by anything my side, so will respond if I find that the issue is not related to the version upgrade.
Message:
System.TypeInitializationException : The type initializer for 'FakeItEasy.ServiceLocator' threw an exception.
---- System.IO.FileNotFoundException : Could not load file or assembly 'Microsoft.Cds.Sdk.Proxy, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified.
Stack Trace:
ServiceLocator.Resolve[T]()
A.get_FakeAndDummyManager()
A.Fake[T]()
XrmFakedContext.ctor(IMiddlewareBuilder middlewareBuilder)
MiddlewareBuilder.ctor()
MiddlewareBuilder.New()
DynamicsContext.ctor() line 22
AccountServiceTests.CreateAgentReadOnly() line 308
<>c.<ThrowAsync>b__128_0(Object state)
----- Inner Stack Trace -----
RuntimeAssembly.GetExportedTypes()
<>c.<FindBootstrapper>b__0_2(Assembly assembly)
SelectManySingleSelectorIterator`2.MoveNext()
WhereEnumerableIterator`1.MoveNext()
Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Boolean& found)
Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
BootstrapperLocator.FindBootstrapper()
RootModule.RegisterDependencies(IServiceRegistrar registrar)
ServiceLocator.cctor()
This might be a duplicate of this old issue from v1: jordimontana82/fake-xrm-easy#584
Testing a query which would be written like this in SQL:
select * from salesOrder s,
salesorderdetail d
where d.quantity is not null
AND
((d.productname = "A" AND d.description = "B")
OR
(d.productname = "C" AND d.productnumber = "D"))
In other words it has a nested sub query against the link-entity, where 2 conditions must both be true OR 2 different conditions must both be true.
Here's how it would look in fetchXMLBuilder and it returns results for both of the OR conditions:
Here's the query:
QueryExpression query = new QueryExpression("salesorder");
// link to salesorderdetail
LinkEntity query_salesorderdetail = query.AddLink("salesorderdetail", "salesorderid", "salesorderid");
// Quantity not null
query_salesorderdetail.LinkCriteria.AddCondition("quantity", ConditionOperator.NotNull);
// Add an 'Or' filter
FilterExpression OrFilter = new FilterExpression();
query_salesorderdetail.LinkCriteria.AddFilter(OrFilter);
OrFilter.FilterOperator = LogicalOperator.Or;
// Filter with two Ands - A and B
FilterExpression aAndBFilter = new FilterExpression();
aAndBFilter.AddCondition("productname", ConditionOperator.Equal, "A");
aAndBFilter.AddCondition("description", ConditionOperator.Equal, "B");
// Filter with two Ands - C and D
FilterExpression cAndDFilter = new FilterExpression();
cAndDFilter.AddCondition("productname", ConditionOperator.Equal, "C");
cAndDFilter.AddCondition("description", ConditionOperator.Equal, "D");
// Add the two and filters to the Or Filter
OrFilter.AddFilter(aAndBFilter);
OrFilter.AddFilter(cAndDFilter);
EntityCollection installers = service.RetrieveMultiple(query);
and here's my initialisation:
SalesOrder order = new SalesOrder() { Id = Guid.NewGuid() };
SalesOrderDetail detail1 = new SalesOrderDetail() { Id = Guid.NewGuid(), SalesOrderId = order.ToEntityReference()
, Quantity = 1, ProductName = "A", Description = "B" };
SalesOrderDetail detail2 = new SalesOrderDetail() { Id = Guid.NewGuid(), SalesOrderId = order.ToEntityReference()
, Quantity = 1, ProductName = "C", Description = "D" };
_context.Initialize(new Entity[] { order, detail1, detail2 });
The query should return two records, but it returns none.
I can provide a Unit Test, but want to check if this is already a known issue before I do.
Add release notes generation to all packages:
And same for 3x branches:
The current implementation relies on Dictionary data structures as the internal implementation of entity records and entity metadata records. Such data structure is not thread safe.
Therefore, we need to replace current In-Memory instances of Dictionary by a different implementation like ConcurrentDictionary and rewrite current code accessing the In-Memory state in a way that is also thread-safe.
This is prior work need to support features like #51 #38 among others.
Linked to jordimontana82/fake-xrm-easy#570
Linked to issue in jordimontana82/fake-xrm-easy#454
Using the latest DataverseClient to connect using AuthType works however XrmRealContext fails with the same connection string.
Sample code
var fakedContext = new XrmRealContext("XrmDebug");
var whoAmIRequest = new WhoAmIRequest();
var response = fakedContext.GetOrganizationService().Execute(whoAmIRequest) as WhoAmIResponse;
Using the same connection string with::
var service = new Microsoft.PowerPlatform.Dataverse.Client.ServiceClient(connstring);
More info jordimontana82/fake-xrm-easy#479
.netcore will be effectively supported in 3x versions only and removed from v2.x versions
Update sonar quality gate in github actions of following repos:
Associated to v1 in this PR jordimontana82/fake-xrm-easy#483
Only add new or update existing ones, but not clearing all previous messages
This issue was raised to provide mocks for the ServiceClient class, however, a much neater and simpler solution would be that the ServiceClient constructor could take an IOrganizationService interface, similar to the already existing internal constructor that MSFT is using for testing their own client:
microsoft/PowerPlatform-DataverseServiceClient#413 (comment)
Add the ability to inspect plugin registration attributes via reflection and automatically register those steps when pipeline simulation is enabled in middleware.
Linked to PR in v1: jordimontana82/fake-xrm-easy#474
Hi @jordimontana82,
a weird cosmetic issue in LINQPad. Don't really know if it's a LINQpad issue or a FXE issue.
With the v1 Nuget packages, it's possible in the LINQPad NuGet package manager to see which version of CRM the package references:
but with the v2/3 packages, it's no longer possible to distinguish them - they all look the same, so it's much harder to chose the right version - you have to select each version in turn in order to be able to see the ID value:
This isn't true in Visual Studio:
Was there some additional info in the NuGet manifest which LINQPad was previously using which is no longer there in v2/3?
Let me know if you need more info or if I can help testing this.
Thanks,
Ben
Concurrency Behavior can be specified in the Update and Delete messages.
This is about raising an exception when IfRowVersionMatches property is specified and the RowVersion provided in the request differs from the current one in the In-Memory database.
Some info in the MS Docs here
There is a filter on entityname='mycontact' in unittest ConditionOperatorTests.FetchXml_EntityName_Attribute_Alias_Execution()
. If the context is initialized with _context.EnableProxyTypes(Assembly.GetExecutingAssembly());
, this test will fail due to the fact that the attribute of the filter is believed to be on the root entity (account) instead of the link-entity (contact).
System.NullReferenceException
HResult=0x80004003
Message=Object reference not set to an instance of an object.
Source=FakeXrmEasy.Core
StackTrace:
FakeXrmEasy.Core.dll!FakeXrmEasy.XrmFakedContext.FindReflectedAttributeType(System.Type earlyBoundType, string sEntityName, string attributeName) Line 114
at C:\Projects\Stuff\fake-xrm-easy-core\src\FakeXrmEasy.Core\XrmFakedContext.Queries.cs(114)
FakeXrmEasy.Core.dll!FakeXrmEasy.Extensions.FetchXml.XmlExtensionsForFetchXml.GetConditionExpressionValueCast(string value, FakeXrmEasy.Abstractions.IXrmFakedContext ctx, string sEntityName, string sAttributeName, Microsoft.Xrm.Sdk.Query.ConditionOperator op) Line 959
at C:\Projects\Stuff\fake-xrm-easy-core\src\FakeXrmEasy.Core\Extensions\XmlExtensionsForFetchXml.cs(959)
FakeXrmEasy.Core.dll!FakeXrmEasy.Extensions.FetchXml.XmlExtensionsForFetchXml.ToConditionExpression(System.Xml.Linq.XElement elem, FakeXrmEasy.Abstractions.IXrmFakedContext ctx) Line 767
at C:\Projects\Stuff\fake-xrm-easy-core\src\FakeXrmEasy.Core\Extensions\XmlExtensionsForFetchXml.cs(767)
In order to making the cloning and building of all the different repos and packages a bit more seamless, the build script could be improved to:
When we try to regiser a step with the "AssociateEntities" message against a custom plugin, he exception is thrown.
There are probably loads of them (i..e another example is AddAppComponents message against appmodule).
Unhandled Exception: System.ServiceModel.FaultException1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=9.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: Custom SdkMessageProcessingStep is not allowed on the specified message. Detail: <OrganizationServiceFault xmlns="http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <ActivityId>6faddc9b-2257-458e-8452-904ffec799b1</ActivityId> <ErrorCode>-2147204729</ErrorCode> <ErrorDetails xmlns:a="http://schemas.datacontract.org/2004/07/System.Collections.Generic"> <KeyValuePairOfstringanyType> <a:key>ApiExceptionSourceKey</a:key> <a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">Plugin/Microsoft.Crm.ObjectModel.SdkMessageProcessingStepService</a:value> </KeyValuePairOfstringanyType> <KeyValuePairOfstringanyType> <a:key>ApiSourceActivityKey</a:key> <a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema" /> </KeyValuePairOfstringanyType> <KeyValuePairOfstringanyType> <a:key>ApiExceptionOwnerKey</a:key> <a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">OwnershipNotFoundInExceptionOwnerSettings</a:value> </KeyValuePairOfstringanyType> <KeyValuePairOfstringanyType> <a:key>ApiOriginalExceptionKey</a:key> <a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">Microsoft.Crm.CrmException: Custom SdkMessageProcessingStep is not allowed on the specified message. ---> Microsoft.Crm.CrmException: Custom SdkMessageProcessingStep is not allowed on the specified message. at Microsoft.Crm.ObjectModel.SdkMessageProcessingStepServiceInternal
1.VerifyIsCustomAllowedOnFilter(IBusinessEntity entity, ExecutionContext context)
at Microsoft.Crm.ObjectModel.SdkMessageProcessingStepServiceInternal1.VerifyData(IBusinessEntity entity, IBusinessEntity inputEntity, ExecutionContext context) at Microsoft.Crm.ObjectModel.SdkMessageProcessingStepServiceInternal
1.CreateInternal(IBusinessEntity entity, ExecutionContext context, Boolean validateData, Boolean verifySku, Boolean checkInternalStage)
at Microsoft.Crm.ObjectModel.SdkMessageProcessingStepServiceInternal`1.CreateInternal(IBusinessEntity entity, ExecutionContext context, Boolean verifySku)
--- End of inner exception stack trace ---
at Microsoft.Crm.Extensibility.VersionedPluginProxyStepBase.Execute(PipelineExecutionContext context)
at Microsoft.Crm.Extensibility.PipelineInstrumentationHelper.Execute(Boolean instrumentationEnabled, String stopwatchName, ExecuteWithInstrumentation action, PipelineExecutionContext context)
at Microsoft.Crm.Extensibility.Pipeline.<>c__DisplayClass3_0.<RunStep>b__0()</a:value>
<a:key>ApiStepKey</a:key>
<a:value i:type="b:guid" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/">54cabb1b-ea3e-db11-86a7-000a3a5473e8</a:value>
<a:key>ApiDepthKey</a:key>
<a:value i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">1</a:value>
<a:key>ApiActivityIdKey</a:key>
<a:value i:type="b:guid" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/">6faddc9b-2257-458e-8452-904ffec799b1</a:value>
<a:key>ApiPluginSolutionNameKey</a:key>
<a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">System</a:value>
<a:key>ApiStepSolutionNameKey</a:key>
<a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">System</a:value>
<a:key>ApiExceptionCategory</a:key>
<a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">ClientError</a:value>
<a:key>ApiExceptionMessageName</a:key>
<a:value i:type="b:string" xmlns:b="http://www.w3.org/2001/XMLSchema">SdkCustomProcessingStepIsNotAllowed</a:value>
<a:key>ApiExceptionHttpStatusCode</a:key>
<a:value i:type="b:int" xmlns:b="http://www.w3.org/2001/XMLSchema">400</a:value>
http://go.microsoft.com/fwlink/?LinkID=398563&error=Microsoft.Crm.CrmException%3a80044187&client=platform
Custom SdkMessageProcessingStep is not allowed on the specified message.
2022-04-04T07:56:32.0107585Z
false
6faddc9b-2257-458e-8452-904ffec799b1
-2147204729
Custom SdkMessageProcessingStep is not allowed on the specified message.
2022-04-04T07:56:32.0107585Z
false
Server stack trace:
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at Microsoft.Crm.Tools.Libraries.RegistrationHelper.RegisterStep(CrmOrganization org, CrmPluginStep step)
at Microsoft.Crm.Tools.PluginRegistration.StepRegistrationViewModel.RegisterStep(Object sender, EventArgs e)
Here's a fetchXml query. It returns the count of 'work notification jobs', grouped by technician name, number and id.
When run against a real (d365 online) instance, the grouped by columns are returned in the query:
When run against FakeXrmEasy v1,2 or 3 the AttributeCollection returned by the query only contains the count, but not the group by columns:
I'm not sure if this a known issue from v1. I can provide a failing test if required, using OOB entities.
More details on: jordimontana82/fake-xrm-easy#545
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.