Ben Walker
  • Blog
  • Blog

Mocking unimplemented organisation requests in FakeXrmEasy

10/7/2021

0 Comments

 
FakeXrmEasy is an invaluable tool for development of Dynamics CRM/365/Dataverse software and using it will make your life as a developer much easier and will undoubtedly help you write more robust, maintainable code. FakeXrmEasy implements an in-memory version of the XRM database and provides mocked version of most of the main methods provided by the IOrganisation service. You may, however, occasionally come across a method which has not been implemented in the library. When you test code which calls one of these methods, your test will fail with a message like this: The organization request type 'Microsoft.Crm.Sdk.Messages.NameOfTheUnimplementedRequest' is not yet supported... but we DO love pull requests so please feel free to submit one! :). This functionality is not available yet. Please consider contributing to the following Git project https://github.com/jordimontana82/fake-xrm-easy by cloning the repository and issuing a pull request."
My first reaction when I came across this test was dismay as I thought that I would not be able to continue testing without first having to implement the unimplemented method, but in fact, this is far from the case. The library provides a number of ways to very easily to invoke these unimplemented methods without having to contribute to the FakeXrmEasy project.

Whilst I would encourage everyone to contribute to this or any other Open Source project, there is actually good reason why some of these requests are unimplemented - in fact, there is no need for all organisation requests to be implemented in the FakeXRMEasy library.

Clearly, the most obvious reason for a method not being implemented in FakeXrmEasy is that the XRM SDK is growing all of the time, and the FakeXrmEasy contributors may never have the time to implement the ever growing number of requests.

Another reason, however, is that not every method needs to be implemented as Microsoft themselves have implemented it, because this is not, or should not, be relevant to your testing. Take, as an example, the OrganisationRequest which converts a Word Template into a PDF document as discussed here. For the contributors to the FakeXrmEasy project to try and implement this request would be a collosal waste of time, and there is a very high chance that their implementation would be nothing like Microsoft's. But why would you need a faked implementation of this method to produce the same output as Microsoft's? Your tests should really not be interested in the contents of the PDF that gets produced - it's Microsoft's job to test that their implementation works correctly, and your unit tests should not really care about the actual contents of the PDF.

Be that as it may, if you have code which at some point calls this particular Organisation Request, you don't want your tests to fail with the "not yet supported..." error message, and I will show you a couple of ways in which you can very easily implement fakes of these methods so that you can continue testing what's important - ie, your own code.

AddExecutionMock
This is the easiest way to add a mocked execution of an Organisation request to your tests and acording to Jordi Montaña, "should be used when you just want to override something ocasionally. AddExecutionMock is the easiest since you can override one fake message easily inline with your unit test." As a simple example, let's look at faking a method which does nothing but return a simple Success or Failure response. An example of this is the CalculateRollupFieldRequest - If we have a plugin which calls this method, we most likely don't really care how Microsoft implements this in the background, we just want to be able to call it from our plugin and for the request not to fail. We can do this using the AddExecutionMock method.

To do this, we need to add a call to AddExecutionMock when we are initialising our test, after we have instantiated our faked context, so our initialisation might look like this:

    
We now need to add our own mocked implementation of the CalculateRollUpFieldRequest method. As the CalculateRollUpFieldRequest returns a CalculateRollupFieldResponse, our implementation just needs to return a CalculateRollupFieldResponse.
Code Editor

    
If our code needs to check the outcome of the request for some reason, then it can set the properties of the response like this:

    
That's all it takes to Mock this request. Your unit tests should now continue to work when they hit the call to CalculateRollUpFieldRequest. There is also a RemoveExecutionMock method which you can call if you want to remove this mocked execution, which might be useful if you wanted to write two different implementations (if, for example, you wanted to be able to test what happens when your response returns failure rather than success). This can just be called like this:

    
Another example - mocking the generation of a PDF from a Word Tempalate
Another example of how easily an OrganisationRequest can be mocked is the OrganisationRequest I mentioned earlier which converts a Word Template to a PDF. Our tests should not really care about the content of the PDF generated, but if called from our code, the method does need to return something, so how do we go about adding a faked implementation of this request?

As before we need to add a faked implementation to our faked context when we initialise our tests:

    
We then need to add a faked version of the request - the OrganisationRequest we are faking has a property called "PdfFile" and returns the PDF as a byte stream, but we really don't need to return a fully formed PDF, so we can just fake the request and its response like this:

    
As before, we have the option of calling the RemoveExecutionMock() method if we want to implement the method if a different way during this test execution.

AddFakeMessageExecutor
According to Jordi, "if you want to override a message that is meant to be more generic and re-used across tests, then the AddFakeMessageExecutor is meant to be used for that, since you can encapsulate the logic in a separate class and pass it your context in every test". The implementation of the FakeMessageExecutor is slightly more complex, but not significantly so. The most significant difference with this method is that it gets the test execution passed into it. This means that, as Jordi says, the implementation can be written into a seperate class which does not need to 'know' the context of the Unit Test, as the context will be passed in as a parameter when called.

Let's take as an example this time a slightly more complex OrganisationRequest, the CloseIncidentRequest. If we do not care the outcome of this request, we could just implement this as a method which returns an empty CloseIncidentResponse in the same way as our first example above. But if we want the request to act in the same way as a real CloseIncidentRequest would by creating an IncidentResolution entity in the database and changing the Status and Status reason of the Incident, we can do this as well, using the context.
As before we start by adding a call to the AddFakeMessageExecutor method when we initialise our test.

    
We then need to implement the faked version of the request by implementing an instance of the IFakeMessageExecutor interface:

    
That's all it takes to add a Fake implementation of the CloseIncidentRequest. As before, there is a RemoveFakeMessageExecutor method which can be used to remove this faked implementation if you need to use more than one faked implementation in your test class.

AddGenericFakeMessageExecutor
Finally, the FakeXrmEasy library contains a method AddGenericFakeMessageExecutor which "was added to be able to execute late bound custom actions and out of the box requests which didn't have an OrganizationRequest class generated in the SDK but could still be invoked by creating an OrganizationRequest manually. "

Jordi continues: "I think some devs wanted it to test calling some out of the box messages that were accessible in the API, but that really, shouldn't be called as it was supposed to be unsupported doing so.... :D  I kept it because it's still useful for users who still use late bound actions...."

I've never had to use this, but it works very similarly to the AddFakeMessageExecutor, and I'll make sure that I update this blog post if I do find myself using it. As with pretty much everything else in FakeXrmEasy, there are Unit Tests in the source code which demonstrate how to use this. Here's an example: https://github.com/jordimontana82/fake-xrm-easy/blob/f294b9af7319f8e23d4032a9290ec75a628f2435/FakeXrmEasy.Tests.Shared/FakeContextTests/TestGenericMessageExecutors.cs

I hope this blog has helped explain how easy it is to write faked implementations of Organisation Requests which have not been implemented in FakeXrmEasy. Happy Testing!
0 Comments



Leave a Reply.

    Archives

    July 2021
    June 2021
    May 2020
    March 2020
    December 2019
    October 2019
    June 2018
    February 2018
    October 2017
    September 2017
    August 2017
    May 2017
    April 2017

    Categories

    All
    Dynamics 365
    Dynamics CRM
    FakeXrmEasy
    LINQPad
    Testing

    RSS Feed

    Author

    Some stuff about me!

Proudly powered by Weebly