It is just testable, isn’t? So what? This has been one of the most common arguments I have heard from people who don’t understand testable designs. The fact of the matter is, unit tests are your design, and they are executable too. You are writing your tests first not just to write unit tests; instead, unit tests help you to think about the design of the problem you are trying to solve, the code you are going to write, and verify their correctness, too.
In TDD, you start writing unit tests before writing a single line of your implementation code (of your plug-in). This test will fail and be marked as red. Next step is to implement the code to make this test pass or make it green. You continue to keep writing tests which fail (red) and refactor or implement your code to make these tests green. Finally, when you feel that you have completed the implementation and have enough code coverage, you are done.
The plug-in in question here is for pre-create of a contact entity which validates the birthday of a contact. For this sample, the plugin will prevent the creation of a contact with future birthdays.
I will be using xUnit as the testing framework. You may use any unit testing framework. Installing xUnit is dead easy. Install it from NuGet using package manager in Visual Studio. Install xunit.runners.visualstudio package to help Visual Studio discover your unit tests.
Below test checks whether the plugin fires for only the event it is registered for. Please note the FakeServiceProvider class of which instance is passed to the execute method.
As expected, this test will fail.
Let us implement the plugin code and the FakeServiceProvider implementation to make the above test pass.
Still, our test is failing. We haven’t implemented FakeServiceProvider yet. From the above code, it is obvious that we should implement FakePluginExecutionContext as well. Implement IPluginExecutionContext and return PreCreate from the MessageName getter property.
Return the new instance of FakePluginExecutionContext from GetService method of FakeServiceProvider
Hooray!!! Our test is passing.
Let us see whether we get the exception if we execute the plugin for a message for which it is not registered for.
For the above test to pass, I had to refactor the FakeServiceProvider and FakePluginExecutionContext classes to accept parameters through their constructors. You can clearly see the power of composition here.
Both our tests are passing. The second test captures the exception and compares the message.
Before we write unit tests for checking the business logic (contact’s birth date should not be greater than today) we should write some infrastructure code and associated unit tests to check the existence of PreImage and the PreImage entity name. I am omitting those details for brevity, but you can check the source code for details here.
Below are the two unit tests for checking the birthdate logic — one positive and one negative.
Please note that the PreImage is passed as a parameter to the constructor of the FakePluginExecutionContext class. This way, we can influence the test results.
Our plugin code can be refactored to move some of the boilerplate code to a base class. Also, FakePluginExecutionContext and FakeServiceProvider classes can be made reusable and complete by implementing the missing methods. Currently, plugin and unit test code are in the same assembly. We can move the plugin code to its own assembly and add a reference in the unit test project.
You might have already noticed that majority of our unit test methods do not have Asserts. For a TDD purist, this could be a big no no. But we have not much of a choice as Execute method returns void. What this means is, it is difficult to make some of the tests fail.
Anyhow, I hope you got some ideas about Test Driven Development especially in the context of writing a CRM plug-in. Hope you write many more unit tests for your plug-ins.