To create a simple test harness for your plug-ins you just need to create a few classes that implement the IServiceProvider, IOranizationServiceFactory, and IPluginExecutionContext interfaces.
First is the TestServiceProvider Class. This class is responsible for providing the plugin execution context and service factory to the plug-in.
public class TestServiceProvider : IServiceProvider{private TestPluginContext _pluginContext;public TestServiceProvider(TestPluginContext pluginContext){_pluginContext = pluginContext;}
public object GetService(Type serviceType){if (serviceType == typeof(IPluginExecutionContext)){return _pluginContext;}if (serviceType == typeof(IOrganizationServiceFactory)){return new TestServiceFactory();}return null;}}
Next is the TestServiceFactory class. This class is responsible for generating the service proxy that the plug-in will be using. For this example I am just returning a new OrganizationServiceProxy (from the referenced Microsoft.Xrm.Sdk.dll assembly), and I have hard-coded connection info. This means that when the plug-in runs, even in the test, it will still be hitting the CRM server. You could also easily return a "fake" organizationservice that didn't actually connect to the CRM server, but just verified that the plug-in was making the correct service calls.
public class TestServiceFactory : IOrganizationServiceFactory{public IOrganizationService CreateOrganizationService(Guid? userId){Uri serviceUrl = new System.Uri("http://crmserver/org/xrmservices/2011/organization.svc");ClientCredentials creds = new ClientCredentials();creds.Windows.ClientCredential = new System.Net.NetworkCredential("username", "pass", "domain");
OrganizationServiceProxy _serviceProxy = new Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy(serviceUrl, null, creds, null);_serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());return _serviceProxy;}}
Finally, you have the TestPluginContext class. This is our fake plugin context that we will fill with the desired test information before executing the plug-in. Note that I am making a WhoAmI request in the constructor to set the InitiatingUserId and OrganizationId properties. This is mostly because I was testing several plug-ins that needed to use those two fields.
public class TestPluginContext : IPluginExecutionContext{public TestPluginContext(){this.InputParameters = new ParameterCollection();this.OutputParameters = new ParameterCollection();
//set the userid and the orgid on the contextIOrganizationService service = new TestServiceFactory().CreateOrganizationService(null);WhoAmIResponse whoAmI = (WhoAmIResponse)service.Execute(new WhoAmIRequest());this.InitiatingUserId = whoAmI.UserId;this.OrganizationId = whoAmI.OrganizationId;
}
public IPluginExecutionContext ParentContext { get; set; }public int Stage { get; set; }public Guid BusinessUnitId { get; set; }public Guid CorrelationId { get; set; }public int Depth { get; set; }public Guid InitiatingUserId { get; set; }public ParameterCollection InputParameters { get; set; }public bool IsExecutingOffline { get; set; }public bool IsInTransaction { get; set; }public bool IsOfflinePlayback { get; set; }public int IsolationMode { get; set; }public string MessageName { get; set; }public int Mode { get; set; }public DateTime OperationCreatedOn { get; set; }public Guid OperationId { get; set; }public Guid OrganizationId { get; set; }public string OrganizationName { get; set; }public ParameterCollection OutputParameters { get; set; }public EntityReference OwningExtension { get; set; }public EntityImageCollection PostEntityImages { get; set; }public EntityImageCollection PreEntityImages { get; set; }public Guid PrimaryEntityId { get; set; }public string PrimaryEntityName { get; set; }public Guid? RequestId { get; set; }public string SecondaryEntityName { get; set; }public ParameterCollection SharedVariables { get; set; }public Guid UserId { get; set; }}
Now that we have the necessary classes set up, we can create a test. To execute the plugin, you just create a new TestPluginContext and fill it with the data needed to test your plug-in. Then create a new TestServiceProvider from the TestPluginContext, and then pass the service provider to the Execute method of your plug-in.
TestPluginContext pluginContext = new TestPluginContext();pluginContext.InputParameters["Target"] = user;pluginContext.PrimaryEntityName = "systemuser";pluginContext.MessageName = "Update";
TestServiceProvider provider = new TestServiceProvider(pluginContext);
MyPlugin plugin = new MyPlugin();plugin.Execute(provider);
Guid buid = new Guid("EF0C0FD0-B50B-E011-8E3F-001DD8B71C42"); //old businessunitGuid newBuid = new Guid("14880f34-711e-e011-b23e-001dd8b71c42"); //new businessunit
Entity user = new Entity("systemuser");user["businessunitid"] = new EntityReference("businessunit", newBuid);user["internalemailaddress"] = "erik.pool@example.com";user["fullname"] = "Erik Pool";user["systemuserid"] = new Guid("4C72C28A-5A0C-E011-892F-001DD8B71C42");
Entity preImage = new Entity("systemuser");preImage["businessunitid"] = new EntityReference("businessunit", buid);preImage["internalemailaddress"] = "erik.pool@example.com";preImage["fullname"] = "Erik Pool";
TestPluginContext pluginContext = new TestPluginContext();pluginContext.InputParameters["Target"] = user;pluginContext.PreEntityImages = new EntityImageCollection();pluginContext.PreEntityImages["Target"] = preImage;pluginContext.PrimaryEntityName = "systemuser";pluginContext.MessageName = "Update";
TestServiceProvider provider = new TestServiceProvider(pluginContext);SystemUserPostUpdatePlugin plugin = new SystemUserPostUpdatePlugin();plugin.Execute(provider);