What did you expect to happen?
I expected to be able to stub an arrow function in a class.
What actually happens
I can't stub an arrow function, however, I can stub the class prototype function.
FAILED TESTS:
ExampleClass tests
× should stub thisDoesntWork arrow function
Chrome 52.0.2743 (Windows 10 0.0.0)
TypeError: Attempted to wrap undefined property thisDoesntWork as function
at wrapMethod (webpack:///~/sinon/pkg/sinon.js:3138:0 <- test-bundler.js:7377:21)
at Object.stub (webpack:///~/sinon/pkg/sinon.js:2472:0 <- test-bundler.js:6711:12)
at Context.<anonymous> (webpack:///src/stores/sinon.test.ts:22:51 <- test-bundler.js:96197:72)
How to reproduce
export class ExampleClass {
thisWorks() {
return 0;
}
thisDoesntWork = () => {
return 0;
}
}
describe("ExampleClass tests", () => {
it("should stub thisWorks function", () => {
let stubFunctionA = sinon.stub(ExampleClass.prototype, "thisWorks");
});
it("should stub thisDoesntWork arrow function", () => {
let stubFunctionB = sinon.stub(ExampleClass, "thisDoesntWork");
});
});
This is food for the upcoming new documentation site where we hope to publish some more tutorial oriented articles on stubbing, spying, etc in the context of ES2015.
Generally when you come across issues like this it is very helpful in remembering one simple fact: ES2015 is often just syntactic sugar on top of simple ES5 constructs. Meaning, when you don't understand why something happens (or doesn't happen), try deconstructing the code into its ES5 equivalent. The simplest way (which is what I just did) is to just paste the example code into the Babel playground and see what the ES2015/ES6 code compiles into:
The transpiled code from Babel
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var ExampleClass = exports.ExampleClass = function () {
function ExampleClass() {
_classCallCheck(this, ExampleClass);
this.thisDoesntWork = function () {
return 0;
};
}
_createClass(ExampleClass, [{
key: "thisWorks",
value: function thisWorks() {
return 0;
}
}]);
return ExampleClass;
}();
The first thing I spot is that arrow functions are simply _instance methods_. That means a few things:
Knowing all of this, it is simply to change your failing test to this:
it("should stub thisDoesntWork arrow function", () => {
var example = new ExampleClass();
let stubFunctionB = sinon.stub(example, "thisDoesntWork", () => "actually it does work" );
});
Good luck.
Most helpful comment
This is food for the upcoming new documentation site where we hope to publish some more tutorial oriented articles on stubbing, spying, etc in the context of ES2015.
Generally when you come across issues like this it is very helpful in remembering one simple fact: ES2015 is often just syntactic sugar on top of simple ES5 constructs. Meaning, when you don't understand why something happens (or doesn't happen), try deconstructing the code into its ES5 equivalent. The simplest way (which is what I just did) is to just paste the example code into the Babel playground and see what the ES2015/ES6 code compiles into:
The transpiled code from Babel
The first thing I spot is that arrow functions are simply _instance methods_. That means a few things:
Knowing all of this, it is simply to change your failing test to this:
Good luck.