XrmUnitTest and FakeXrmEasy are two testing frameworks that are specifically targeted towards Dynamics CRM/Dynamics 365. It is possible to do both unit test as well as integration tests using both these frameworks. In this first post, I would like to cover FakeXrmEasy. Here is a sample plugin code that I would like to test:
using Microsoft.Xrm.Sdk;
using System;
using Microsoft.Crm.Sdk.Messages;
namespace SamplePlugin
{
public class LastNameUpperCasePlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
ITracingService tracer = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
try
{
Entity entity = (Entity)context.InputParameters["Target"];
//not required. Just added to demonstrate that we are connecting to a real crm org service
var response = service.Execute(new WhoAmIRequest());
var lastName = entity.GetAttributeValue<string>("lastname");
if (!string.IsNullOrEmpty(lastName))
{
entity["lastname"] = lastName.ToUpper();
}
}
catch (Exception e)
{
throw new InvalidPluginExecutionException(e.Message);
}
}
}
}
In order to test this plugin, we have to create a unit test project. Here are the steps for it:
- Create a unit test project from the existing plugin solution by right clicking and choose Add->New Project->Visual C#->Test->Unit Test Project
- Use nuget to add the correct FakeXrmEasy reference to the test project. In this example I am using “FakeXrmEasy.365” as I am connecting to a Dynamics 365 instance online. Refer https://www.nuget.org/profiles/jmontana to find out all the different versions that are relevant to your CRM version.
- Create a App.config file, if it doesn’t already exist. Here is my connection string. Refer https://msdn.microsoft.com/en-us/library/mt608573.aspx to find the correct format of the connection string for you crm instance.

Below is my test for the plugin
using System;
using System.Collections.Generic;
using System.Web.Configuration;
using FakeXrmEasy;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Xrm.Sdk;
namespace SamplePlugin.Test
{
[TestClass]
public class LastNamePluginUnitTests
{
[TestMethod]
public void Should_Set_LastName_In_UpperCase()
{
var context = new XrmRealContext
{
ProxyTypesAssembly = typeof(LastNameUpperCasePlugin).Assembly,
ConnectionStringName = "CRMOnline"
};
var executionContext = context.GetDefaultPluginContext();
var target = new Entity("contact")
{
["lastname"] = "Power",
Id = Guid.NewGuid()
};
executionContext.MessageName = "Create";
executionContext.Stage = 20;
executionContext.PrimaryEntityId = target.Id;
executionContext.PrimaryEntityName = target.LogicalName;
executionContext.InputParameters = new ParameterCollection
{
new KeyValuePair<string, object>("Target", target)
};
context.ExecutePluginWith<LastNameUpperCasePlugin>(executionContext);
Assert.AreEqual("POWER",
((Entity) executionContext.InputParameters["Target"]).GetAttributeValue<string>("lastname"));
}
}
}
In this test I am creating a scenario where the plugin is running pre-create. You can change to add pre/post entity images or target a different message and stage. If we debug our integration test, we can see that we are connected to the real org service.

I have used latebound entity in this example, but you can use the same code with early bound entities generated using crmsvcutil or Early Bound Generator.
You can use a similar approach for testing custom workflow assemblies as well. In that case you would be using “GetDefaultWorkflowContext” instead of “GetDefaultPluginContext” to get the execution context.
Footnote: Technically this test could have been better written as an unit test instead of a integration test. But the purpose of this post is to demonstrate the points below:
- How to build a fake plugin execution context
- How to use connection strings to create a real OrganizationService instance
- How to use the real OrganizationService with the fake plugin execution context
EDIT (22/11/2016): Thank you Jonas (@rappen) for pointing out the plugin stage should be pre-create for this to work. Updated context stage to 20.