I am working on a project where I am observing types of each binding layer function that node.js javascript layer calls. For observing types, I created a stub using sinon
that looks something like this
var originalProcessBinding = process.binding;
sinon.stub(process, 'binding').callsFake(function (data) {
var res = originalProcessBinding(data);
// custom code here
return res;
}
So, my idea is to look at each object
inside res
and see if its a Function
. If it is, create a stub that records the state and then call the original Function
. The custom code
looks something like
_.forEach(res, function(value, key) {
if (_.isFunction(value)) {
sinon.stub(res, key).callsFake(function() {
var args = arguments;
// do some processing with the arguments
save(args);
// call the original function
return value(...arguments);
}
}
}
However, I am not sure if this handles all the types of returns. For instance, how are the errors handled? What happens if the function is asynchronous?
I ran the node.js
test suite and found lots of failing test cases. Is there a better way to stub the functions. Thanks.
Edit: The failing test cases have errors in common that look like Callback was already called
or Timeout
or Expected Error
.
Unfortunately, even though many errors can be fixed, It's hard to add sinon
to the build process. I implemented by own stubbing methods in vanilla js to fix this. Anyone who's looking to stub internal node.js
functions should find this helpful.
(function() { process.binding = function(args) {
const org = process.binding;
const util = require('util');
var that = org(args),
thatc = that;
for (let i in thatc) {
if (util.isFunction(thatc[i]) && (!thatc[i].__isStubbed)) {
let fn = thatc[i];
if (i[0] !== i[0].toUpperCase()) {
// hacky workaround to avoid stubbing function constructors.
thatc[i] = function() {
save(arguments);
return fn.apply(that, arguments);
}
thatc[i].__isStubbed = true;
}
}
}
return thatc;
}
})();
This code passes all the tests with the current master of Node.js. Adding sinon
seems to mutate the function object that triggers internal v8 checks which fail.