I am an advocate of using unit testing wherever possible. This is because it allows repeatable tests to run, usually in a fraction of a second. Using unit tests allows me to be confident that later updates will not affect the current functionality.

One of the issues with unit testing I had with unit testing for Dynamics plugins & coded activities is that I did not want the unit test to run directly against the Dynamics instance. The two main reasons for this are:

  1. I did not want to be performing actions against an instance because part of the reason the test could fail is if the record the test is expecting to be there has been deleted
  2. I did not want to test the connection to the platform. The unit tests should just test the code, not the overall platform.

Mocks

To prevent connecting to an actual instance, we can utilise Mocks.

In a unit test, mock objects can simulate the behavior of complex, real objects and are therefore useful when a real object is impractical or impossible to incorporate into a unit test.

https://en.wikipedia.org/wiki/Mock_object

In this example, I will be using a Mocking Framework called FakeXrmEasy. This is a fantastic framework which allows most (if not all) of Dynamics functionality to be replicated. The website provides good examples of how to use it – but I’ll go through another example in this post.

Test Scenario

The plugin that I will be using for this example is simple. It trigger on PreOperation when an Account is created. It will take the name & address1_city fields and concatenate them into another field called new_nameandcity.

The tests that I will run on this plugin are:

  1. It should work when name and address1_city are provided
  2. It should throw an exception when address1_city is not provided

Installation

In my example, I have created a new Unit Test project (I am using MS Test, but this framework does work with others, like NUnit). Inside the Unit Test project, open NuGet and search for FakeXrmEasy, then install the version that matches your target instance of Dynamics.

Alternatively, you can use the NuGet console to install directly from the command line – the names follow the pattern ‘FakeXrmEasy.version’, for exampleFakeXrmEasy.365.

Plugin Modification

If you are using the Dynamics 365 Toolkit to generate the plugin structure, then you should see that the plugin constructor accepts secure & unsecure configuration as parameters.

For the unit test framework to be able to access the plugin, another constructor needs to be added which accepts no parameters. I thought that a parameterless constructor had to be added, but Betim Beja has pointed out that he has updated the framework to allow the plugin instance to be created & then passed it to ExecutePlugin.

In this example, I have also added a property which I use to determine if the plugin is being executed by the unit test runner or by the Dynamics system. I have done this to highlight that sometimes your code may need to be modified to run correctly in both environments. In my example, I am running on Create in PreOperation. If the code is executed within Dynamics, then the Update command cannot be called at the end otherwise an exception is shown regarding record not existing. However, if Update is not ran in the test, then the record is not Updated and the test fails.

Code

The two unit tests are included below. A sample project has also been uploaded to GitHub.

Account Created Unit Test – Successful

Account Created Unit Test – Exception Thrown

Summary

Hopefully you can see how easy unit testing can be when using the FakeXrmEasy framework. Although unit testing can cause a bit more work upfront, it easily pays for itself through reduced bugs being introduced at later dates.

Unit testing will also allow more confidence when refactoring or adding new functionality as you can re-run all of the tests in seconds to make sure none of the previous functionality has changed.

It is important to remember that unit tests need to be maintained overtime. If the functionality is meant to change, then the unit test needs to be updated to include this. You may also forget to test certain scenarios, when this is noticed, the unit tests should be added again. The aim is to have every execution path covered.

Further Functionality

In a previous post, I demonstrated using Azure DevOps (was previously named Visual Studio Team Services) pipelines to automated deployment of managed solutions using Dynamics 365 Build Tools. It is possible to integrate unit tests into the pipeline, to prevent deployment of solutions if the unit tests fail. I will cover how to do this in a later blog.

This Post Has One Comment

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Close Menu
%d bloggers like this: