Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write mock for 3rd party library with nested functions (javascript, jasmine)

I'm new to TDD and I am trying to write testable code which uses a third party libraries (cross platform mobile development). I would like to have tests to only to check our business logic. Not to worry about their implementation.

More over their libraries are exposed only in native wrappers. Since use js as development language I would like to test using jasmine and run test to check my business logic only in browser.

Here are the patterns of methods I would like to ignore/mock when testing.

com.companyname.net.checkInternetAvailable(url) 

com.companyname.store.getValue(key)

com.companyname.someother.name(whateverObj, callback) etc.,

At the moment, I have created a new mocks.js file where I simply wrote

var com = {
    "net":{},
    "store":{},
    "someother":{}
}

com.net.checkInternetAvailable = function(url){
    //TODO: fix this!
    return true;
}

and I do the same for all the methods in my code. I tried to use Jasmine SpyOn(com.net, "checkInternetAvailable").and.returnValue(true) instead of defining all the methods. Problem with this approach is I had to define all the methods to use SpyOn.

Is there a simpler way to do this? What is the recommended approach?

like image 728
palaniraja Avatar asked Mar 10 '16 20:03

palaniraja


1 Answers

One approach you could take is to use the Sinon javascript test library to stub the third party library methods. These stubbed methods can then be set-up to mimic results which would be difficult to reproduce using the actual third party library. Your system under test (SUT) could then make use of these stubbed methods inside of your Jasmine tests.

I've written a contrived example here:

https://jsfiddle.net/Fresh/uf8owzdb/

The code is as follows:

// A module which has methods you want to stub
Net = (function() {

  // Constructor
  function Net() {
  }

  Net.prototype.checkInternetAvailable = function(url) {
    return true;
  };

  return Net;

})();

// A method which is dependent on the Net module
var methodWhichUsesNet = function(net) {
    return net.checkInternetAvailable();
};

// Stub the method behaviour using Sinon javascript framework.
// For the test, get it to return false instead of true.
var net = new Net();
var expectedResult = false;
sinon.stub(net, "checkInternetAvailable").returns(expectedResult);

// Assert method behaviour using a Jasmine test
describe("Net test suite", function() {
  it("methodWhichUsesNet should return expected result", function() {
    expect(methodWhichUsesNet(net)).toBe(expectedResult);
  });
});

Note that it is advisable to stub the third party methods as you want to control exactly what they should return, as you know which methods your code is making use of. Alternatively you could mock these third party methods if you also want to verify that these methods are called by the method which uses them. You could stub the entire third party object methods using e.g.:

var stub = sinon.stub(obj);

However I would advise against doing this as it would mean that the test would not be as explicit i.e. you would not be sure as to how the stubbed methods are behaving, whereas stubbing them explicitly means you have complete control of their behaviour.

like image 144
Ben Smith Avatar answered Sep 22 '22 19:09

Ben Smith