Search code examples
javascriptunit-testingsapui5sinonqunit

How to Write Unit Tests for Functions That Contain SAPUI5 Core API?


I'm new to qUnit with UI5.

I want to test one function formatter.js

formatDate: function(sTimeStamp) {
  if (sTimeStamp) {
    var iTimeStamp = Number(sTimeStamp.match(/\d/g).join("")), 
        oDateTimeFormat = DateFormat.getDateTimeInstance(); 
    return oDateTimeFormat.format(new Date(iTimeStamp));
  }
  return sTimeStamp;
},

Unit test for it:

function formatDateTestCase(assert, sValue, fExpectedNumber) {
  var fDate = formatter.formatDate(sValue);
  assert.strictEqual(fDate, fExpectedNumber, "Format Date was correct");
}

QUnit.test("Should return valid date", function (assert) {
  formatDateTestCase.call(this, assert, "/Date(1510026665790)/", "Nov 7, 2017, 11:51:05 AM");
});

Obviously, this test case will fail when I change language setting. How to improve it?


I think the main problem here is that formatDate is a function with side effects. Should I improve this function itself? By adding locale in formatDate?

Or should I use DateFormat in my test case? Which will make my test meaningless.


Solution

  • I think you should mock the calls to DateFormat here to be able to independently test your code.

    Unit Test Considerations

    Strictly speaking the point of a Unit Test is to test your - and only your - Unit. You should not test any dependent API. One could argue about that in general but I would definitely NOT recommend to test SAPUI5 API.

    One the other hand I would strongly recommend to test the if statement and the Regex part with invalid params (e.g. undefined) and invalid strings. This will ensure your formatter to always work and to return sth. meaningful if it is an empty string.

    Sinon.JS: Mocks, Stubs and Spys

    You should stub DateFormat.getDateTimeInstance() in your specific test so that the method returns a predictable value (e.g. think of I18N in DateFormat that would give you different test results in different languages).

    To do that SAPUI5 already ships with Sinon.JS (be aware of the version included: SAPUI5 1.44 -> Sinon.JS 1.14). Here is a basic example:

    sap.ui.define([
      "my/module/formatter",
      "sap/ui/core/format/DateFormat",
      "sap/ui/thirdparty/sinon",
      "sap/ui/thirdparty/sinon-qunit"
    ], function (formatter, DateFormat) {
    
      QUnit.test("Should return valid date", function (assert) {
        // stub the method
        sinon.stub(DateFormat, "getDateTimeInstance");
        // ensure a predictable outcome
        DateFormat.getDateTimeInstance.returns({
          format: function(oDate) {
            return oDate.getTime();
          }
        });
    
        var fDate = formatter.formatDate("/Date(1510026665790)/");
        assert.strictEqual(fDate, "1510026665790", "Format Date was correct");
        // Optional: test if the stubbed function was called
        assert.ok(DateFormat.getDateTimeInstance.calledOnce);
    
        // don't forget to restore the stub so that it does not interfere with other tests
        DateFormat.getDateTimeInstance.restore();
      });
    
    });
    

    By stubbing DateFormat.getDateTimeInstance you stop testing core API and it's outcomes and you can focus on what matters most: YOUR code.

    BR Chris