When you finished your Dynamics CRM Plugin you need to write a Unit test to achieve 100% code coverage. Writing unit tests can be difficult, time-consuming, and slow when you can't isolate the classes you want to test from the rest of the system. Here are some steps you need to follow and cover your plugin code using Unit test methods.
Here in this blog, I have explained how to write unit test method for different functionality, data types and events like Retrieve, Retrieve Multiple, PreImage data, Post Image data, Entity, EntityReference, Option set, TargetEntity data, etc.
How to create a Unit test project: Create Unit test project in VS 2019
Step 1
Add Fakes references to your MS project

The Fakes Assemblies will automatically be created in your project.
Now you can start writing your Unit test method code.
Always remember Unit test for the plugin is passing hardcoded value only. The plugin does not connect with the CRM database while writing the Unit test methods.
Step 2
Use Fakes libraries in your Unittest.cs file

Now the below code is for every test method will be same. It contains the declaration, Initialization of the IPlugin interface.
- /// <summary>
- /// Organization Service Response
- /// </summary>
- private OrganizationResponse response = new CreateResponse();
- /// <summary>
- /// Gets or sets Service Provider
- /// </summary>
- private static StubIServiceProvider ServiceProvider { get; set; }
- /// <summary>
- /// Gets or sets Plugin Execution Context
- /// </summary>
- private static StubIPluginExecutionContext PluginExecutionContext { get; set; }
- /// <summary>
- /// Gets or sets Organization Service
- /// </summary>
- private static StubIOrganizationService OrganizationService { get; set; }
- /// <summary>
- /// Gets or sets Test Entity
- /// </summary>
- private Entity TestEntity { get; set; }
- /// <summary>
- /// Class Initialize
- /// </summary>
- /// <param name="textContext">text Context</param>
- [ClassInitialize]
- public static void ClassInit(TestContext textContext)
- {
- var context = new StubIPluginExecutionContext();
- var tracingService = new StubITracingService();
- var orgFactory = new StubIOrganizationServiceFactory();
- ServiceProvider = new StubIServiceProvider();
- OrganizationService = new StubIOrganizationService();
- PluginExecutionContext = context;
- ////override GetService behaviour and return our stubs
- ServiceProvider.GetServiceType = (type) =>
- {
- if (type == typeof(IPluginExecutionContext))
- {
- return context;
- }
- else if (type == typeof(IOrganizationServiceFactory))
- {
- return orgFactory;
- }
- else if (type == typeof(ITracingService))
- {
- return tracingService;
- }
- else if (type == typeof(IOrganizationService))
- {
- return OrganizationService;
- }
- return null;
- };
- ////return our stub organizationservice
- orgFactory.CreateOrganizationServiceNullableOfGuid = (userId) => OrganizationService;
- ////write trace logs to output. only works when debugging tests
- tracingService.TraceStringObjectArray = (message, args) => Debug.WriteLine(message, args);
- }
- /// <summary>
- /// Initialize Test File
- /// </summary>
- [TestInitialize]
- public void TestInit()
- {
- ////setup initial values for each test
- var inputParameters = new ParameterCollection();
- PluginExecutionContext.InputParametersGet = () => inputParameters;
- this.TestEntity = new Entity();
- inputParameters.Add(new KeyValuePair<string, object>("Target", this.TestEntity));
- }
- /// <summary>
- /// Test Cleanup
- /// </summary>
- [TestCleanup]
- public void TestCleanup()
- {
- this.TestEntity = null;
- }

Join the conversation! Your thoughts help the community grow.