jeudi 25 mai 2017

Writing testable TypeScript classes for Dynamics CRM

How do you write a class for a Dynamics CRM form in TypeScript that is testable?

By testable, I mean a non-static class that can be instantiated and passed a mock Xrm object.

My current approach is something like this, but it has limitations (which I explain):

export class Contact {
    Xrm: Xrm.XrmStatic;

    constructor(xrm?: Xrm.XrmStatic) {
        this.Xrm = xrm;
    }

    onLoad(): void {
       if (this.Xrm) { Xrm = this.Xrm; }
       // ...
    }
}

Firstly, the Contact class is exported so that can be referenced by a CRM form. CRM can't instantiate an object before calling it's functions, so to call these methods I use Contact.prototype.onLoad in the CRM form designer.

My test looks like this:

beforeEach(function () { 
    this.XrmMock = new XrmStaticMock();
    this.contact = new Contact(this.XrmMock);
    this.contact.onLoad();
}

it('does stuff', function () {
    // ...
}

The test is able to instantiate Contact and pass XrmMock to the constructor. Subsequently when onLoad() is called, it evaluates if (this.Xrm) to true, and uses XrmMock. Conversely, when Contact.prototype.onLoad() is called from within CRM, (this.Xrm) is false because Contact has never been instantiated. Therefore any reference to Xrm within onLoad() uses the default Xrm namespace (which is what we want). We want this because when a CRM form is opened, the real Xrm dependency is loaded by the browser.

The limitation here is having to write a conditional check in every method which wants to use the Xrm dependency. How can this be overcome?

Here's a link to documentation on the Xrm.Page object model. My classes and Xrm mock are written using @types/xrm.


I appreciate I'm asking multiple questions here, if you think you can guide me to writing a more specific question, please let me know :)

Aucun commentaire:

Enregistrer un commentaire