### Install Main FakeXrmEasy Package Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/installing Installs the main FakeXrmEasy package for your relevant version of Dataverse/Dynamics CRM. Use this for a general setup. ```powershell Install-Package FakeXrmEasy.{ v9 | v365 | v2016 | v2013 | v2011 } -Version 2 | 3 ``` -------------------------------- ### Setup for SubmitNewIncidentCommand Tests Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/advanced/interaction-testing Sets up the necessary models, organization, and portal user for testing the SubmitNewIncidentCommand. This includes initializing the command with a service context. ```csharp public class SubmitNewIncidentCommandTests: FakeXrmEasyTestsBase { private readonly ISubmitNewIncidentCommand _submitCommand; private readonly IGetOrganisationSupportPlanCommand _suportPlanCommand; private readonly SubmitIncidentModel _model; private readonly Account _organisation; private readonly dv_portal_user _portalUser; public SubmitNewIncidentCommandTests() { _model = new SubmitIncidentModel() { Title = "Engine is broken", Description = "I need a technician onsite ASAP!" }; _organisation = new Account() { Id = Guid.NewGuid() }; _portalUser = new dv_portal_user() { Id = Guid.NewGuid() }; _submitCommand = new SubmitNewIncidentCommand(_service) { Model = _model, OrganisationId = _organisation.Id, PortalUserId = _portalUser.Id }; } [Fact] public void Should_return_error_if_support_plan_failed() { //Create a command that returns a failed command _supportPlanCommand = FakeCommandFactory.GetFailedCommand(); //Create a new submit command and inject the support plan command as a property dependency _submitCommand.GetOrganisationSupportPlanCommand = _supportPlanCommand; //Verify submit fails in this scenario var result = _submitCommand.Execute(); Assert.False(result.Succeeded); //Verify the interaction Assert.Equal(_submitCommand.OrganisationId, _supportPlanCommand.OrganisationId); } [Fact] public void Should_return_error_if_there_is_no_support_plan() { //Create a command that returns OrganisationSupportPlanType.None _supportPlanCommand = FakeCommandFactory.GetSuccessfulCommand(OrganisationSupportPlanType.None); //Create a new submit command and inject the support plan command as a property dependency _submitCommand.GetOrganisationSupportPlanCommand = _supportPlanCommand; //Verify submit fails in this scenario var result = _submitCommand.Execute(); Assert.False(result.Succeeded); //Verify the interaction Assert.Equal(_submitCommand.OrganisationId, _supportPlanCommand.OrganisationId); } [Fact] public void Should_create_incident_with_low_priority_if_basic_support_plan() { //Create a command that returns OrganisationSupportPlanType.Basic _supportPlanCommand = FakeCommandFactory.GetSuccessfulCommand(OrganisationSupportPlanType.Basic); _submitCommand.GetOrganisationSupportPlanCommand = _supportPlanCommand; var result = _submitCommand.Execute(); //Verify it succeeds and that a new Low priority Incident is created Assert.True(result.Succeeded); var incidentCreated = _context.CreateQuery().FirstOrDefault(); Assert.NotNull(incidentCreated); Assert.Equal(_model.Title, incidentCreated.Name); Assert.Equal(_model.Description, incidentCreated.Description); Assert.Equal(IncidentPriority.Low, (IncidentPriority) incidentCreated.dv_priority.Value); Assert.Equal(_organisation.Id, incidentCreated.dv_organisationid.Id); Assert.Equal(_portalUser.Id, incidentCreated.dv_raisedbyid.Id); //Verify the interaction Assert.Equal(_submitCommand.OrganisationId, _supportPlanCommand.OrganisationId); } [Fact] public void Should_create_incident_with_high_priority_if_premium_support_plan() { ``` -------------------------------- ### Install FakeXrmEasy Plugins Package Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/installing Installs the FakeXrmEasy.Plugins package, which is necessary for developing and testing plugins. Specify the version relevant to your project. ```powershell Install-Package FakeXrmEasy.Plugins.vxxx -Version 2.x ``` -------------------------------- ### Install All-Inclusive FakeXrmEasy Package (.NET Framework) Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/installing Installs the main FakeXrmEasy package for .NET Framework, which includes Core, Messages, Plugins, and CodeActivities. Use this for projects with a mixture of components. ```powershell Install-Package FakeXrmEasy.vxxx -Version 2.x ``` -------------------------------- ### Setup Pipeline Simulation Middleware Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/plugins/pipeline/basics Enable pipeline simulation by adding the UsePipelineSimulation() middleware. This should be placed before other middleware to ensure PreOperation steps fire correctly. ```csharp public class FakeXrmEasyPipelineTestsBase { protected readonly IXrmFakedContext _context; protected readonly IOrganizationService _service; public FakeXrmEasyPipelineTestsBase() { _context = MiddlewareBuilder .New() .AddCrud() .AddFakeMessageExecutors() .AddPipelineSimulation() .UsePipelineSimulation() .UseCrud() .UseMessages() .Build(); _service = _context.GetAsyncOrganizationService(); } } ``` -------------------------------- ### Install All-Inclusive FakeXrmEasy Package (.NET 8.0) Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/installing Installs the main FakeXrmEasy package for .NET 8.0, which includes Core, Messages, Plugins, and CodeActivities. Use this for projects with a mixture of components. ```powershell Install-Package FakeXrmEasy.vxxx -Version 3.x ``` -------------------------------- ### Setup Pipeline Simulation Middleware Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/middleware Configure the Fake Xrm Easy context to include pipeline simulation capabilities. This is useful for testing plugin executions. ```csharp public class FakeXrmEasyTestsBase { protected readonly IXrmFakedContext _context; protected readonly IOrganizationServiceAsync2 _service; public FakeXrmEasyTestsBase() { _context = MiddlewareBuilder .New() .AddCrud() .AddFakeMessageExecutors() .AddPipelineSimulation() .UsePipelineSimulation() .UseCrud() .UseMessages() .SetLicense(FakeXrmEasyLicense.RPL_1_5) .Build(); _service = _context.GetAsyncOrganizationService2(); } } ``` -------------------------------- ### Setup Empty Initial State Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/testing-with-data To test logic that creates new records without querying existing ones, simply avoid calling the .Initialize() method. ```csharp // Just don't call .Initialize() ;) ``` -------------------------------- ### Install FakeXrmEasy Messages Package Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/installing Installs the FakeXrmEasy.Messages package, which contains implementations for further OrganizationRequests. Specify the version relevant to your project. ```powershell Install-Package FakeXrmEasy.Messages.vxxx -Version 2.x ``` -------------------------------- ### Install FakeXrmEasy Core Package Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/installing Installs the minimal FakeXrmEasy.Core package, ideal for testing Azure Functions or other client applications. The version depends on whether you are targeting .NET Core (3.x) or .NET Framework (2.x). ```powershell Install-Package FakeXrmEasy.Core.vxxx -Version 2.x ``` -------------------------------- ### Install FakeXrmEasy.Plugins Package Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/plugins/overview Install the FakeXrmEasy.Plugins package targeting .NET Framework and CRM SDK v9.x. Ensure you are using version 2.x for plugin development and testing. ```powershell Install-Package FakeXrmEasy.Plugins.v9 -Version 2.x ``` -------------------------------- ### Install FakeXrmEasy CodeActivities Package Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/installing Installs the FakeXrmEasy.CodeActivities package for developing and testing code activities in traditional workflows. Specify the version relevant to your project. ```powershell Install-Package FakeXrmEasy.CodeActivities.vxxx -Version 2.x ``` -------------------------------- ### Install FakeXrmEasy CodeActivities v9 Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/codeactivities Install the FakeXrmEasy.CodeActivities.v9 package to enable testing of code activities. Ensure you are using version 2.x. ```powershell Install-Package FakeXrmEasy.CodeActivities.v9 -Version 2.x ``` -------------------------------- ### Install FakeXrmEasy for Dynamics 365/Dataverse v9 (Plugins) Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/installing Installs FakeXrmEasy.v9 for developing and testing plugins when using v9 of Dynamics 365 or Dataverse. This targets .NET Framework. ```powershell Install-Package FakeXrmEasy.v9 -Version 2.2.0 ``` -------------------------------- ### Minimal Middleware Setup with CRUD Operations Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/middleware Sets up the FakeXrmEasy middleware with support for basic CRUD operations. This configuration is often placed in a base test class for reuse across multiple tests. Ensure you comply with the licensing terms. ```csharp public class FakeXrmEasyTestsBase { protected readonly IXrmFakedContext _context; protected readonly IOrganizationServiceAsync2 _service; public FakeXrmEasyTestsBase() { _context = MiddlewareBuilder .New() .AddCrud() .UseCrud() // Here we are saying we're using FakeXrmEasy (FXE) under a commercial context // For more info please refer to the license at https://dynamicsvalue.github.io/fake-xrm-easy-docs/licensing/license/ // And the licensing FAQ at https://dynamicsvalue.github.io/fake-xrm-easy-docs/licensing/faq/ .SetLicense(FakeXrmEasyLicense.Commercial) .Build(); _service = _context.GetAsyncOrganizationService2(); } } ``` -------------------------------- ### Setup Initial State with Relationships Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/testing-with-data Model relationships between entities by setting lookup fields (EntityReference) on one entity to reference another. This pattern is useful for reusing data across multiple tests. ```csharp public class MyAccountTests: FakeXrmEasyTestsBase { private readonly Account _account; private readonly Contact _contact; public MyAccountTests() { _contact = new Contact() { Id = Guid.NewGuid() }; _account = new Account() { Id = Guid.NewGuid(), PrimaryContactId = _contact.ToEntityReference() //the Account is associated with the above contact record }; } [Fact] public void Should_have_a_primary_contact() { _context.Initialize(new List() { _account, _contact }); //Execute whatever logic.... } } ``` -------------------------------- ### Install FakeXrmEasy for Dynamics 365/Dataverse v9 (Azure Functions/Client Apps) Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/installing Installs FakeXrmEasy.v9 for developing and testing Azure Functions or other client applications when using v9 of Dynamics 365 or Dataverse. This targets .NET Core. ```powershell Install-Package FakeXrmEasy.v9 -Version 3.2.0 ``` -------------------------------- ### Register Plugin Step for Any Entity Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/plugins/pipeline/basics Register a plugin step for a specific message and stage. This example registers the AccountNumberPlugin for the PreOperation stage of the Create message, applicable to any entity. ```csharp using FakeXrmEasy.Pipeline; public class PipelineTests: FakeXrmEasyPipelineTestsBase { [Fact] public void Should_set_account_number_on_account_create() { _context.RegisterPluginStep("Create", ProcessingStepStage.Preoperation); _context.ExecutePluginWith(); var account = _context.CreateQuery().FirstOrDefault(); Assert.NotNull(account); Assert.True(account.Attributes.ContainsKey("accountnumber")); Assert.NotNull(account["accountnumber"]); } } ``` -------------------------------- ### Configure FakeXrmEasy with Custom API Executors Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/messages/custom-apis Tell FakeXrmEasy where to find your custom API executors by adding them during middleware setup. This allows FakeXrmEasy to automatically discover and use them. ```csharp _context = MiddlewareBuilder .New() .AddCrud() .AddFakeMessageExecutors(Assembly.GetAssembly(typeof(AddListMembersListRequestExecutor))) //This is the important bit .AddCustomApiFakeMessageExecutors(Assembly.GetAssembly(typeof(CustomApiSumFakeMessageExecutor))) .AddPipelineSimulation(new PipelineOptions() { UsePluginStepAudit = true }) .UsePipelineSimulation() .UseCrud() .UseMessages() .SetLicense(FakeXrmEasyLicense.RPL_1_5) .Build(); ``` -------------------------------- ### Testing Async Methods with xUnit Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/advanced/async Test asynchronous operations in xUnit by marking your test methods with the 'async' keyword and using 'await' for async calls. This example demonstrates creating a contact asynchronously. ```csharp public class CreateContactTests : FakeXrmEasyTestsBase { [Fact] public async void Should_create_contact() { var result = await CreateContactFn.CreateContact(_service, "Joe", "joe@satriani.com"); Assert.True(result.Succeeded); var contacts = _context.CreateQuery("contact").ToList(); Assert.Single(contacts); Assert.Equal("Joe", contacts[0]["firstname"]); Assert.Equal("joe@satriani.com", contacts[0]["emailaddress1"]); } } ``` -------------------------------- ### Register Plugin Step with Plugin Images Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/plugins/pipeline/registration Set up PreImages or PostImages for a plugin step. Images act as snapshots of the entity record before or after the operation, accessible within the plugin. ```csharp string registeredPreImageName = "PreImage"; PluginImageDefinition preImageDefinition = new PluginImageDefinition(registeredPreImageName, ProcessingStepImageType.PreImage); _context.RegisterPluginStep("Update", registeredImages: new PluginImageDefinition[] { preImageDefinition }); ``` -------------------------------- ### Unit Tests for GetOrganisationSupportPlanCommand Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/advanced/interaction-testing Contains unit tests for the GetOrganisationSupportPlanCommand, covering scenarios with no support plan, basic, and premium plans. Uses xUnit theories for efficient testing of multiple data inputs. ```csharp public class GetOrganisationSupportPlanCommandTests : FakeXrmEasyTestsBase { private readonly IGetOrganisationSupportPlanCommand _command; private readonly dv_support_plan _supportPlan; private readonly Account _organisation; //The more entity records we can setup in the constructor, the smaller and easier to read each unit test will be public GetOrganisationSupportPlanCommandTests() { _organisation = new Account() { Id = Guid.NewGuid() }; _supportPlan = new dv_support_plan() { Id = Guid.NewGuid(), dv_organisationid = _organisation.ToEntityReference() //support plan associated to current org via this property }; _command = new GetOrganisationSupportPlanCommand(_service) //fake org service from base test class { OrganisationId = _organisation.Id }; } [Fact] public void Should_return_none_if_there_is_no_support_plan() { //No need to setup any test data for this scenario var result = _command.Execute(); Assert.True(result.Succeeded); //verify it succeded with no exceptions var supportPlan = (result as GenericResult).Model; //verify the response model is "None" Assert.Equal(OrganisationSupportPlanType.None, supportPlan); } [Theory] [InlineData(OrganisationSupportPlanType.Basic)] [InlineData(OrganisationSupportPlanType.Premium)] public void Should_return_relevant_organisation_plan_type_based_on_support_plans_plan_type(OrganisationSupportPlanType planType) { //We need one support plan to test this scenario: _supportPlan.dv_plantype = new OptionSetValue((int) planType); _context.Initialize(_supportPlan); var result = _command.Execute(); Assert.True(result.Succeeded); var supportPlan = (result as GenericResult).Model; Assert.Equal(planType, supportPlan); //matches all of InlineData combinations } } ``` -------------------------------- ### Set Commercial License for IXrmFakedContext Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/licensing/commercial-license-setup Use this when building an IXrmFakedContext to indicate usage in a commercial context. Ensure FakeXrmEasy v2 or later is installed. ```csharp public class FakeXrmEasyTestsBase { protected readonly IXrmFakedContext _context; protected readonly IOrganizationServiceAsync2 _service; public FakeXrmEasyTestsBase() { _context = MiddlewareBuilder .New() .AddCrud() .UseCrud() //Here we are saying we're using FakeXrmEasy (FXE) under a commercial context .SetLicense(FakeXrmEasyLicense.Commercial) .Build(); _service = _context.GetAsyncOrganizationService2(); } } ``` -------------------------------- ### Initialize In-Memory File Storage with Files Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/file-storage/initializing Use this method to set the initial state of the In-Memory FileDb with a set of pre-existing files. Ensure the target entity record is initialized first, and that the FileAttachment includes the correct Target entity reference and attribute name. ```csharp var _entity = new Entity(dv_test.EntityLogicalName) { Id = Guid.NewGuid(), }; var _file = new FileAttachment() { Id = Guid.NewGuid().ToString(), MimeType = "application/pdf", FileName = "TestFile.pdf", Target = _entity.ToEntityReference(), AttributeName = FILE_ATTRIBUTE_NAME, Content = new byte[] { 1, 2, 3, 4 } }; _entity[FILE_ATTRIBUTE_NAME] = _file.Id; _context.Initialize(_entity); _context.InitializeFiles(new [] { _file }); ``` -------------------------------- ### Interface for Get Organisation Support Plan Command Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/advanced/interaction-testing Defines an interface for a command that retrieves an organization's support plan. Requires an OrganisationId. ```csharp public interface IGetOrganisationSupportPlanCommand: IOrgServiceCommand { Guid OrganisationId { get; set; } } ``` -------------------------------- ### Get All Files in Fake XRM Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/file-storage/querying Retrieve all file attachments currently stored in the in-memory database. This method is suitable for fetching all available files. ```csharp var _fileDb = (_context as XrmFakedContext).FileDb; var lisOfFiles = _fileDb.GetAllFiles(); ``` -------------------------------- ### Add Necessary Usings for Middleware Configuration Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/migrating-from-1x/technical_guidance Include these namespaces when setting up the new middleware configuration for FakeXrmEasy. ```csharp using FakeXrmEasy.Abstractions; using FakeXrmEasy.Abstractions.Enums; using FakeXrmEasy.FakeMessageExecutors; using FakeXrmEasy.Middleware; using FakeXrmEasy.Middleware.Crud; using FakeXrmEasy.Middleware.Messages; ``` -------------------------------- ### Basic Plugin Unit Test with FakeXrmEasy Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/plugins/overview Unit test a plugin by providing a default PluginExecutionContext and setting necessary properties like InputParameters and Target. Execute the plugin using ExecutePluginWith and assert the outcome by querying the in-memory database. ```csharp using FakeXrmEasy.Plugins; public class MyFollowUpPluginTests : FakeXrmEasyTestsBase { public MyFollowUpPluginTests() { } [Fact] public void When_the_followup_plugin_is_executed_for_an_account_after_create_it_should_create_a_new_task_with_a_regardingid() { _context.EnableProxyTypes(Assembly.GetExecutingAssembly()); //Needed to be able to return early bound entities //Get a default plugin execution context that will invoke actions against the In-Memory database automatically var pluginContext = _context.GetDefaultPluginContext(); //Set the necessary properties of the pluginExecution context that the plugin will need var guid1 = Guid.NewGuid(); var target = new Entity("account") { Id = guid1 }; ParameterCollection inputParameters = new ParameterCollection(); inputParameters.Add("Target", target); ParameterCollection outputParameters = new ParameterCollection(); outputParameters.Add("id", guid1); pluginContext.InputParameters = inputParameters; pluginContext.OutputParameters = outputParameters; //Execute the plugin with the fake PluginExecutionContext _context.ExecutePluginWith(pluginContext); //Assert: The plugin creates a followup activity, check that that one exists var tasks = (from t in _context.CreateQuery() select t).ToList(); Assert.True(tasks.Count == 1); Assert.True(tasks[0].Subject.Equals("Send e-mail to the new customer.")); Assert.True(tasks[0].RegardingObjectId != null && tasks[0].RegardingObjectId.Id.Equals(guid1)); } } ``` -------------------------------- ### Configure Automatic Plugin Step Registration Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/plugins/pipeline/automatic-registration Use this configuration within the AddPipelineSimulation method to enable automatic plugin step registration. Specify the assemblies containing your plugins and provide a custom discovery function. ```csharp .AddPipelineSimulation(new PipelineOptions() { UsePluginStepAudit = true, UseAutomaticPluginStepRegistration = true, PluginAssemblies = new List() { Assembly.GetAssembly(typeof(FollowUpPlugin)) }, CustomPluginStepDiscoveryFunction = PluginStepDiscoveryFn }) ``` -------------------------------- ### Get File by ID in Fake XRM Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/file-storage/querying Retrieve a specific file attachment using its unique identifier. This is useful when you know the exact file you need. ```csharp var _fileDb = (_context as XrmFakedContext).FileDb; var singleFile = _fileDb.GetFileById(_file.Id); ``` -------------------------------- ### GetOrganisationSupportPlanCommand Implementation Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/advanced/interaction-testing Implements the GetOrganisationSupportPlanCommand to retrieve the organization's support plan type. It queries the dv_support_plan entity and returns the appropriate OrganisationSupportPlanType. ```csharp public class GetOrganisationSupportPlanCommand : OrgServiceCommand, IGetOrganisationSupportPlanCommand { public Guid OrganisationId { get; set; } protected override GenericResult ConcreteExecute() { using(var ctx = new XrmServiceContext(_orgService)) { var supportPlan = (from sp in ctx.CreateQuery() where sp.dv_organisationid.Id == OrganisationId select sp.dv_plantype).FirstOrDefault(); if(supportPlan == null) { return GenericResult.Succeed(OrganisationSupportPlanType.None); } else { return GenericResult.Succeed((OrganisationSupportPlanType) supportPlan.Value); } } } } ``` -------------------------------- ### Define IOrgServiceCommand Interface Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/advanced/interaction-testing Implement this interface for all commands. It includes methods to check execution conditions and perform the actual logic, returning a GenericResult. ```csharp /// A command interface that performs an action using an IOrganizationService underneath public interface IOrgServiceCommand { GenericResult CanExecute(); GenericResult Execute(); } ``` -------------------------------- ### FakeCommandFactory for Mocking Commands Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/advanced/interaction-testing Use this factory to create fake implementations of IOrgServiceCommand. It allows mocking successful or failed command executions with generic or typed results. Assertions should be on the main command using these fakes, not on the fakes themselves. ```csharp public class FakeCommandFactory { public static T GetSuccessfulCommand() where T: IOrgServiceCommand { var service = A.Fake(); A.CallTo(() => service.Execute()).ReturnsLazily(() => { return GenericResult.Succeed(); }); return service; } public static T GetSuccessfulCommand(M responseModel) where T: IOrgServiceCommand { var service = A.Fake(); A.CallTo(() => service.Execute()).ReturnsLazily(() => { return GenericResult.Succeed(responseModel); }); return service; } public static T GetFailedCommand(string errorMessage) where T: IOrgServiceCommand { var service = A.Fake(); A.CallTo(() => service.Execute()).ReturnsLazily(() => { return GenericResult.FailWith(errorMessage); }); return service; } public static T GetFailedCommand(M responseModel, string errorMessage = "") where T: IOrgServiceCommand { var service = A.Fake(); A.CallTo(() => service.Execute()).ReturnsLazily(() => { return GenericResult.FailWith(responseModel, errorMessage); }); return service; } } ``` -------------------------------- ### Disable Plugin Step Registration Validation Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/plugins/pipeline/registration_validation To disable plugin step registration validation, set the UsePluginStepRegistrationValidation property to false within PipelineOptions during middleware setup. ```csharp _context = MiddlewareBuilder .New() .AddPipelineSimulation(new PipelineOptions() { UsePluginStepRegistrationValidation = false }) //... other middleware setup... ``` -------------------------------- ### Get Async Organization Service with Cancellation Tokens Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/advanced/async Retrieve the async organization service that supports cancellation tokens using GetAsyncOrganizationService2(). This is useful for operations that can be cancelled. ```csharp public class FakeXrmEasyTestsBase { protected readonly IXrmFakedContext _context; protected readonly IOrganizationServiceAsync2 _service; public FakeXrmEasyTestsBase() { _context = MiddlewareBuilder .New() .AddCrud() .UseCrud() .Build(); _service = _context.GetAsyncOrganizationService2(); } } ``` -------------------------------- ### Plugin with Constructor for Configurations Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/advanced/dependency_injection A plugin constructor designed to receive unsecure and secure configurations during plugin execution. ```csharp public class FollowupPlugin: IPlugin { public FollowupPlugin(string unsecureConfiguration, string secureConfiguration) { } } ``` -------------------------------- ### Get Async Organization Service without Cancellation Tokens Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/advanced/async Retrieve the async organization service that does not use cancellation tokens using GetAsyncOrganizationService(). Use this when cancellation is not a concern. ```csharp public class FakeXrmEasyTestsBase { protected readonly IXrmFakedContext _context; protected readonly IOrganizationServiceAsync _service; public FakeXrmEasyTestsBase() { _context = MiddlewareBuilder .New() .AddCrud() .UseCrud() .Build(); _service = _context.GetAsyncOrganizationService(); } } ``` -------------------------------- ### Add Fake Message Executors with RPL 1.5 License Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/middleware Use AddFakeMessageExecutors to include fake messages from a specified assembly. This example sets the license to RPL 1.5. ```csharp public class FakeXrmEasyTestsBase { protected readonly IXrmFakedContext _context; protected readonly IOrganizationServiceAsync2 _service; public FakeXrmEasyTestsBase() { _context = MiddlewareBuilder .New() .AddCrud() .AddFakeMessageExecutors(Assembly.GetAssembly(typeof(AddListMembersListRequestExecutor))) .UseCrud() .UseMessages() // Here we are saying we're using FakeXrmEasy (FXE) in compliance with the Reciprocal Public License 1.5 // For more info please refer to the license at https://dynamicsvalue.github.io/fake-xrm-easy-docs/licensing/license/ // And the licensing FAQ at https://dynamicsvalue.github.io/fake-xrm-easy-docs/licensing/faq/ .SetLicense(FakeXrmEasyLicense.RPL_1_5) .Build(); _service = _context.GetAsyncOrganizationService2(); } } ``` -------------------------------- ### Configure SubscriptionStorageProvider in Middleware Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/licensing/commercial-license/middleware-setup Add your custom SubscriptionStorageProvider to the FakeXrmEasy middleware configuration. Ensure this is called after .SetLicense and before .Build. ```csharp public class FakeXrmEasyCommercialLicenseTestsBase { protected readonly IXrmFakedContext _context; protected readonly IOrganizationService _service; public FakeXrmEasyCommercialLicenseTestsBase() { _context = MiddlewareBuilder .New() .AddCrud() .AddFakeMessageExecutors(Assembly.GetAssembly(typeof(AddListMembersListRequestExecutor))) .UseCrud() .UseMessages() .SetLicense(FakeXrmEasyLicense.Commercial) // Your provider goes here ... .SetSubscriptionStorageProvider(new SubscriptionBlobStorageProvider()) .Build(); _service = _context.GetOrganizationService(); } } ``` -------------------------------- ### Upload File Block Request Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/file-storage/uploading Use the FileContinuationToken to upload file blocks. Each block requires unique BlockData and a BlockId. This example uploads a single block for simplicity. ```csharp _uploadBlockRequest = new UploadBlockRequest() { BlockData = new byte[] { 1, 2, 3, 4 }, BlockId = new Guid().ToString(), }; _uploadBlockRequest.FileContinuationToken = initFileUploadResponse.FileContinuationToken; _service.Execute(_uploadBlockRequest); ``` -------------------------------- ### SubmitNewIncidentCommand Implementation Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/advanced/interaction-testing Provides the implementation for the SubmitNewIncidentCommand, including dependency injection for commands and logic for creating incidents based on support plan types. It demonstrates how to handle command execution flow and error propagation. ```csharp public class SubmitNewIncidentCommand: OrgServiceCommand, ISubmitNewIncidentCommand { public Guid OrganisationId { get; set; } public Guid PortalUserId { get; set; } public IGetOrganisationSupportPlanCommand GetOrganisationSupportPlanCommand { get; set; } public SubmitIncidentModel Model { get; set; } protected override GenericResult ConcreteExecute() { BuildCommands(); GetOrganisationSupportPlanCommand.OrganisationId = OrganisationId; var supportPlanResult = GetOrganisationSupportPlanCommand.Execute(); if(!supportPlanResult.Succeeded) { return supportPlanResult; } var supportPlan = (supportPlanResult as GenericResult).Model; if(supportPlan == OrganisationSupportPlanType.None) { return GenericResult.FailWith("The current organisation doesn't have a support plan, please buy one"); } return CreateIncidentWithSupportPlan(supportPlan); } protected void BuildCommands() { if(GetOrganisationSupportPlanCommand == null) { GetOrganisationSupportPlanCommand = new GetOrganisationSupportPlanCommand(_orgService); //use the real command, not a fake one } } protected GenericResult CreateIncidentWithSupportPlan(OrganisationSupportPlanType planType) { _orgService.Create(new Incident() { Name = Model.Title, Description = Model.Description, dv_organisationid = new EntityReference(Account.EntityLogicalName, OrganisationId), dv_raisedbyid = new EntityReference(PortalUser.EntityLogicalName, PortalUserId), dv_priority = planType == OrganisationSupportPlanType.Premium ? new OptionSetValue ((int) IncidentPriority.High) : new OptionSetValue ((int) IncidentPriority.Basic) }); return GenericResult.Succeed(); } } ``` -------------------------------- ### Add Fake Message Executors with Non-Commercial License Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/middleware This setup includes fake messages from a specified assembly and sets the license to NonCommercial, suitable for the Modified PolyForm Non-Commercial license 1.0.0. ```csharp public class FakeXrmEasyTestsBase { protected readonly IXrmFakedContext _context; protected readonly IOrganizationServiceAsync2 _service; public FakeXrmEasyTestsBase() { _context = MiddlewareBuilder .New() .AddCrud() .AddFakeMessageExecutors(Assembly.GetAssembly(typeof(AddListMembersListRequestExecutor))) .UseCrud() .UseMessages() // Here we are saying we're using FakeXrmEasy (FXE) in compliance with the Modified PolyForm Non-Commercial license 1.0.0 // For more info please refer to the license at https://dynamicsvalue.github.io/fake-xrm-easy-docs/licensing/license/ // And the licensing FAQ at https://dynamicsvalue.github.io/fake-xrm-easy-docs/licensing/faq/ .SetLicense(FakeXrmEasyLicense.NonCommercial) .Build(); _service = _context.GetAsyncOrganizationService2(); } } ``` -------------------------------- ### Refactor XrmFakedContext to Base Test Class Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/migrating-from-1x/technical_guidance Refactor existing XrmFakedContext constructors to a base class for cleaner test setup. This pattern ensures the middleware is initialized once per test project. ```csharp public class FakeXrmEasyTestBase { protected readonly IOrganizationService _service; protected readonly XrmFakedContext _context; public FakeXrmEasyTestBase() { _context = new XrmFakedContext(); _service = _context.GetOrganizationService(); } } ``` -------------------------------- ### Configure Middleware for Early-Bound Custom Actions Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/messages/custom-actions Set up the FakeXrmEasy middleware to include early-bound custom action execution. This involves adding FakeMessageExecutors using the assembly containing the custom action request types. ```csharp var context = MiddlewareBuilder .New() .AddCrud() .AddFakeMessageExecutors(Assembly.GetAssembly(typeof(new_TestActionRequest))) .UseCrud() .UseMessages() .SetLicense(FakeXrmEasyLicense.RPL_1_5) .Build(); ``` -------------------------------- ### Register Plugin with Custom Instance Source: https://dynamicsvalue.github.io/fake-xrm-easy-docs/quickstart/plugins/pipeline/registration Pass a pre-constructed plugin instance to the plugin step definition using the PluginInstance property. This allows for injecting custom dependencies or using custom constructors. Requires minimum version 2.3.3 or 3.3.3. ```csharp var myPluginInstance = new CustomInstancePluginPipeline("My Injected Value"); _context.RegisterPluginStep(new PluginStepDefinition() { EntityLogicalName = Account.EntityLogicalName, MessageName = "Create", Stage = ProcessingStepStage.Preoperation, Mode = ProcessingStepMode.Synchronous, PluginInstance = myPluginInstance }); ```