From 911c498dc14dc4034ba019526bf58f8b24d77da0 Mon Sep 17 00:00:00 2001 From: Dean Sofer Date: Thu, 7 Dec 2017 05:10:25 -0800 Subject: [PATCH] Spy passes through calling with `new` (#1626) This changes the spy behavior so that if the spy is `calledWithNew()` then the original function will also get called with `new`. This was throwing an error if you tried spying on an ES6 class object. fixes #1265 --- lib/sinon/spy.js | 16 ++++++++++++---- test/spy-test.js | 10 ++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/sinon/spy.js b/lib/sinon/spy.js index 9a44a33be..29c612170 100644 --- a/lib/sinon/spy.js +++ b/lib/sinon/spy.js @@ -17,6 +17,7 @@ var push = Array.prototype.push; var slice = Array.prototype.slice; var filter = Array.prototype.filter; var ErrorConstructor = Error.prototype.constructor; +var bind = Function.prototype.bind; var callId = 0; @@ -190,11 +191,18 @@ var spyApi = { try { this.invoking = true; - returnValue = (this.func || func).apply(thisValue, args); - var thisCall = this.getCall(this.callCount - 1); - if (thisCall.calledWithNew() && typeof returnValue !== "object") { - returnValue = thisValue; + + if (thisCall.calledWithNew()) { + // Call through with `new` + // eslint-disable-next-line new-parens + returnValue = new (bind.apply(this.func || func, [thisValue].concat(args)))(); + + if (typeof returnValue !== "object") { + returnValue = thisValue; + } + } else { + returnValue = (this.func || func).apply(thisValue, args); } } catch (e) { exception = e; diff --git a/test/spy-test.js b/test/spy-test.js index 3d6e41a36..dc68d6d7f 100644 --- a/test/spy-test.js +++ b/test/spy-test.js @@ -439,6 +439,16 @@ describe("spy", function () { assert(called); }); + it("passes 'new' to underlying function", function () { + function TestClass() {} + + var SpyClass = createSpy.create(TestClass); + + var instance = new SpyClass(); + + assert(instance instanceof TestClass); + }); + it("passs arguments to function", function () { var actualArgs;