Testing Dynamics CRM – Plugins | Capsule Series
You are reading the third part of the main article: Testing Dynamics CRM.
A plugin is custom code that runs within CRM’s process. However, when unit testing, we have to isolate the environment in which the plugin code runs. In addition, we need to provide the parameters required to successfully execute.
The first order of business is to analyse the parameters provided to the plugin by its interface definition. CRM provides only one parameter, namely IServiceProvider. This service provider object facilitates the extraction of services. Of which, there are three important ones we all use: IOrganizationServiceFactory, IPluginExecutionContext, and ITracingService.
The Tool
We will mock/fake/simulate the three services as best we can. Well … a really good developer did all the heavy-lifting for us: Jordi Montana.
He created a framework called FakeXrmEasy. Here’s a snippet from his website describing the framework:
FakeXrmEasy is an open source framework built on top of Fake It Easy which adds a layer specifically designed for Dynamics CRM to mock IOrganizationService calls for you. It also keeps track of every entity from plugins, code activities, queries, and any other 3rd party app accessing the IOrganizationService in a context which runs In Memory, blazingly fast.
FakeXrmEasy helps you effectively maintain a healthy CRM ecosystem by reducing the time needed to write tests for: Plugins, Code Activities, and Other code.
https://dynamicsvalue.com/home
FakeXrmEasy is available on NuGet for easy installation into a test project.
IOrganizationService
First step is to create the framework’s main object. The object will handle everything for us, from execution to querying.
var xrmFakedContext = new XrmFakedContext();
There are two types of organisation services. One is connected to a DB in memory, and has nothing to do with CRM’s deployment at all. The other actually connects to CRM directly and runs queries against its API.
Unit tests are pointless if you pollute them with external factors outside their control. Therefore, connecting to CRM directly defeats the point of creating those tests in the first place. I would definitely avoid a direct connection, except maybe to run integration tests.
var service = xrmFakedContext.GetOrganizationService();
IPluginExecutionContext
Now comes the interesting part: building the plugin context. We will add everything the plugin code might ever need from the context. That includes InputParameters, MessageName, UserId, EntityImages … etc.
For example, let’s assume our post-operation plugin is registered on the update of an account number. In addition, it requires a post image containing the account name and fax. The preparation code might look like this:
var target =
new Account
{
Id: Guid.NewGuid(),
AccountNumber: "12345"
};
var image =
new Account
{
Name: "Contoso",
Fax: "111-111-1111"
};
var fakedContext =
new XrmFakedPluginExecutionContext
{
MessageName = "Update",
Stage = 40,
InputParameters = new ParameterCollection { ["Target"] = target },
PostEntityImages = new EntityImageCollection { ["image"] = image }
};
Supporting Data
Assume that the plugin will retrieve the list of related contacts. Therefore, we will proceed with creating one.
var contact =
new Contact
{
FirstName: "John",
LastName: "Doe",
Email: "[email protected]",
CompanyName: new EntityReference(target.LogicalName, target.Id)
};
contact.Id = service.Create(contact);
Notice how we used the faked service to create a record. FakeXrmEasy created the record in a DB in memory for us to query anytime.
Execute
Let’s run the test.
xrmFakedContext.ExecutePluginWith<PostUpdateAccountNotifyContact>(fakedContext);
Notice how we passed the plugin type (PostUpdateAccountNotifyContact) as a type parameter to the execution function.
Assert
After the test has finished, we need to make sure that its effect on the system is what we desire. In our case, the plugin is supposed to create an email. Hence, we should check that one was created.
var query =
new QueryExpression(Email.EntityLogicalName)
{
TopCount = 1,
ColumnSet = new ColumnSet(false)
};
var result = service.RetrieveMultiple(query).Entities;
Assert.IsNotEmpty(result);
Conclusion
What I covered above was the most straightforward scenario to test a plugin. Plugins are not supposed to be complex; therefore, most will be simple enough for the above to satisfy their testing requirements.
For more advanced functionalities, and for testing custom steps, please refer to Jordi’s website.
In the next part of the article, I will try to simplify the already-complex chore that is testing JS code.
2 Responses
[…] its interface definition. CRM provides only one parameter, namely IServiceProvider . This service …read more Read Complete Post and […]
[…] ? […]