简体   繁体   中英

Unit testing functions - passing dependencies as args vs global access

Consider a scenario where a function A depends on three functions — P , Q and R . P, Q, R themselves have been unit tested as they do some really complex computations. Now I need to test the function A and I have two options —

Access P, Q, R directly from A

function A (params) {
   ... P() 
   ... Q() 
   ... R() 
}

PROs: No mocking required except for params.
CONs: Unnecessarily testing the logic of P, Q & R .

Inject P, Q, R as arguments into A

function A (P, Q, R, params) {
   ... P()
   ... Q()
   ... R()
}

PROs: A is tested in a more controlled environment, as P, Q, R as passed as args.
CONs: A lot of effort goes in keeping the mocked functions update to date with their original functions.

I want to know which approach is better of the two and how can I control their respective cons in a better fashion.

NOTE: A, P, Q, R are all pure .

Assuming that your functions P, Q, R are urinary, you can compose them.

// A drop in implementation of compose
var compose = function () {
  var fns = arguments;

  return function (result) {
    for (var i = fns.length - 1; i > -1; i--) {
      result = fns[i].call(this, result);
    }

    return result;
  };
};

var X = compose(R, Q, P);

function A (func, params) {
  // Function body...
}

// Curry function A so that our new function B, matches the signature 
// of the version of function A in your first example from the original           
//question.
var B = A.bind(undefined, X);

// Function B now has the same signature and behavior of function
// A in your first example.
var value = B(args...);

Calling function B in this code will be equivalent to calling function A in the original questions first example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM