Dave Clark IO

Unit test your client-side customisations in Dynamics 365

If you regularly write client-side customisations for Dynamics 365 forms, you should strongly consider writing tests for them. Here's how.

Aug 14th 2017ยท2 min read
light boxes

If you regularly write client-side customisations for Dynamics 365 forms, you should strongly consider writing tests for them.

To do so, you will require a mock implementation of Dynamics' Xrm namespace object: the object you use to manipulate the form with functions such as getAttribute and setRequired. This is because though your code knows about the Xrm object when it's running on a Dynamics form in the browser, your tests won't know about it when running locally on your machine.

Mock the Xrm object

I've begun creating a mock implementation of Xrm here on my GitHub page. It's usage is straightforward, and you can follow my examples if you're using TypeScript to write your client-side customisations.

First, clone the repository using npm install xrm-mock.

Then, create a file for your entity's form. Here's an example for the contact entity:

export namespace Company.Contact {
  export namespace MainForm {
    let contact: Contact;

    export function onLoad(xrm?: Xrm.XrmStatic): void {
      contact = new Contact(xrm || Xrm);
      contact.changeFirstName("Joe");
    }
  }

  class Contact {
    constructor(xrm?: Xrm.XrmStatic) {
      Xrm = xrm || Xrm;
    }

    changeFirstName(newName: string): void {
      Xrm.Page.getAttribute("firstname").setValue(newName);
    }
  }
}

Note: To use this script on a Dynamics form, just add Company.Contact.MainForm.onLoad as one of the form's onLoad() event handlers.

Then, create a second file to test your contact script. The below example is using jasmine.

import * as XrmMock from "xrm-mock";
import { Company } from "../src/contact";

describe("contact", () => {
  beforeEach(() => {
    let attributes: Xrm.Collection.ItemCollection<Xrm.Page.Attribute> = new XrmMock.ItemCollectionMock(
      [new XrmMock.AttributeMock("firstname", "Phil", false, "required")]
    );

    this.Xrm = new XrmMock.XrmStaticMock(
      new XrmMock.PageMock(
        new XrmMock.DataMock(new XrmMock.EntityMock(attributes))
      )
    );
  });
  it("works", () => {
    Company.Contact.MainForm.onLoad(this.Xrm);
    let firstName: string = Xrm.Page.getAttribute("firstname").getValue();

    expect(firstName).toBe("Joe");
  });
});

Now run your tests

You'll now need to configure a test runner. If you've followed my example, you can install jasmine by running the following command in your terminal: npm install jasmine --save-dev. This assumes you have node installed on your machine.

Combined with jasmine, I use wallaby.js to visualise my tests as I'm writing my code. Here it is in action:

Dave Clark IO
AboutLinkedInTwitterGitHub