Bind Mocking Function inside function

2.1k Views Asked by At

I am writing QUnit test case for my application . Basically I have three Files like below . DataServices.js has getObjectDetails method which does ajax call to get data and passes result in callback .

Resolver.js loads DataServices.js using require.

I am writing test case for Proxy.resolve method , in which i want to avoid actual api call , to do this I created mock object of DataServices in Test.js and call Resolver proxy resolve method .

I tried using bind , But still points to actual method of DataServices.js not what I bind in Test.js

DataServices.js

define(["module"], function(module) {
"use strict";
 var Details = {
    getObjectDetails :function(param,callback){
       //API AJAX CALL
       // Callback once done
    }
 };
 return {Details : Details }
});

Resolver.js

define(["DataServices"],function(DataServices){
var Proxy= {
  resolve : function(){
  var Details = DataServices.Details ;
     Details.getObjectDetails("xyz", function(result){
         // Do Operation After Result
     });
  }

 };
 return {Proxy:Proxy}
});

Test.js

define(["Resolver.js" ],function(Resolver){

   var DataServices= {
    Details : {
        getObjectDetails : function(undefined,onSuccess, onError) {
            return onSuccess({"X":"Y"});
        }
      }
   };
  Resolver.Proxy.resolve.bind(DataServices);
  Resolver.Proxy.resolve(); // This is still calling DataServices.js Details 
                            // Not the above muck object

});

In simple program , I want to call mock z function , not z which is inside x . How to achieve this.

var x = {
  z:function(b){
    console.log("Z Actual Function..."+b);
   },
  a : function(){
    this.z(3);
  }
};
var z = function(b){
  console.log("Mock ..."+b)
}

x.a.bind(z);
x.a();

//Z Actual Function...3

But I want Mock ...3 to print

1

There are 1 best solutions below

4
On BEST ANSWER

First problem

Using .bind creates a new function, it doesn't change the value of this in the original function.

To use bind in your case you would do something like this instead:

var mockedA = x.a.bind(z);
mockedA();

If you want to call the function immediately without assigning it to a variable you can use .call or .apply instead.

eg:

x.a.call(z); // runs `a()` immediately with `this` set to `z`

The second problem

By binding x.a to z you're changing the value of this to the value provided (the mock z function). So inside x.a when you call this.z(3) you're effectively trying to call z.z(3), which is a non existent function and so will throw a TypeError.

There are probably better ways of doing it but this is a way that answers your question:

var x = {
  z:function(b){
    console.log("Z Actual Function..."+b);
  },
  a : function(){
    this.z(3);
  }
};

var mock = {};
mock.z = function(b){
  console.log("Mock ..."+b)
}

// with bind
var mockXA = x.a.bind(mock);
mockXA();

// with call
//x.a.call(mock)