In order develop and test plugins you’ll need to use Version 2.x of FakeXrmEasy.Plugins package, as it is the version that targets .NET Framework.
Install-Package FakeXrmEasy.Plugins.v9 -Version 2.x
This will install the plugins package that uses a CRM SDK version v9.x. See Installing for more details about other versions.
That package comes with extension methods that will make it easier to test plugins.
The approach is that you would FakeXrmEasy to provide you with a default PluginExecutionContext, which then you can override based on the plugin logic.
For example, some plugins might fire for multiple messages but do different things based on that message, so you could pass different Message properties for each scenario you want to test.
Let’s assume we’re testing the sample FollowupPlugin plugin (you can find the source code here)
public class FollowupPlugin : IPlugin
{
//Omitted for simplicity, please see the full source code above
}
That plugin could be test with FakeXrmEasy like
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<FollowupPlugin>(pluginContext);
//Assert: The plugin creates a followup activity, check that that one exists
var tasks = (from t in _context.CreateQuery<Crm.Task>()
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));
}
}
This is a specific method overload that doesn’t require passing in a plugin context and it might be useful for plugins that just execute some logic on the Target entity.
If that’s the case, you migh want to use a simpler ExecutePluginWithTarget method.
_context.ExecutePluginWithTarget<FollowupPlugin>(new Account() { Id = Guid.NewGuid() });
There is one very important aspect to consider.
FakeXrmEasy will automatically update the state of the In-Memory database as long as any of the Create / Update / Upsert / Delete / Associate / Disassociate operations are executed on the service.
This means that, from the point of view of testing or asserting the state after the test execution, you could just query the context to retrieve such state using, for example:
var accountAfter = _context.CreateQuery<Account>().FirstOrDefault();
Assert.Equal("Some name", accountAfter.Name);
However, that won’t work if the plugin just modifies the Target (or other plugin context properties) without explicitly calling .Update or any of the above service operations internally (and the plugin, in some cases, shouldn’t do that).
For example, if a plugin that runs in the PreOperation step of an Account Create message, and updates some properties of the target account, those changes will be persisted to the database without calling service.Update(), because it is part of the current database transaction.
So how can we then assert on updates of the Target entity?
Simple: we make the assertions against the exact same object reference that was passed into the plugin.
For example:
var accountTarget = new Account() { Id = Guid.NewGuid() };
_context.ExecutePluginWithTarget<FollowupPlugin>(accountTarget);
Assert.Equal("Some name", accountTarget.Name);