-
-
Notifications
You must be signed in to change notification settings - Fork 771
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support constructor functions and ES6 classes in spies and stubs #1265
Comments
I have a bit of trouble understanding what you are trying to do with the actual code from the top of my head, but I do recognize the heading, which has been covered extensively before. Could you please read the the comment thread in 831 and see if it covers the info on what you are trying to do? Alternatively this or this. I might be totally off on what you are on about, but it bears mentioning that ES6 is just syntactic sugar and there is nothing you cannot do in ES6 regarding classes and constructors that wasn't possible with ES5. So hoping this issue just goes away by itself 🙈 😸 |
@fatso83 Sure, I've already read related issues prior to posting this one. The thing that differs ES6 classes from ES5 constructor functions is a safeguard that prevents them from being used like In the example above |
@bisubus thank you for the details. I was not aware that the spec actually mandates the interpreter to throw an error when not calling the constructor with new, since the transpiled code is working fine. Since this feature is currently not possible to support in ES6/ES2015 environments using ES5-only syntax, we will need to do something à la
We definitively need to support this, so feel free to hack out a PR that patches |
@fatso83 Babel tries to follow the specs strictly (TS doesn't, Traceur too IIRC), so this is applicable to ES5 as well. It is possible to detect native classes with regexps, but not Babel classes, at least in minified code. Did you mean 'stub' when you said 'createStubInstance'? It seems to me that I think there's no real need for
But wouldn't this be an XY problem? Accidental Do you have ideas or comments on incorporating |
Just a minor thing. The example above turned out to (very slightly) incorrect. I was playing around with it and noticed it wasn't actually doing what you said. Factory methods are I took the liberty of adding the I/someone will need to come back to you on the other points you raised. P.S. The OP needs to be rephrased a bit to make it clearer that this is a feature request for more convenience, rather than a bug (unless I am misunderstanding and it is both things). |
@fatso83 Thanks, of course, this was a mistake. I've updated the OP. Since this behaviour existed in spies and stub by design, I guess this is feature request. |
I think the spy should detect that it was called with Can't we just move the This feels like it would fix all the problems we're having. |
I was a bit premature in closing this, I see. #1626 deals explicitly with the spying case, not the stubbing case. Reopening. After seeing the code for the Then after seeing the code @ProLoser supplied for spying on the constructor it dawned upon me that I needed to tilt the perspective over to what the user wants: I would guess what a user wants is to invoke a Sinon method that would enable her to:
I must attest to not understanding the expected code, @bisubus, but is the const sinon = require('./')
const foo = { Bar: class Bar {
static factory() { return new Bar }
constructor(){
this.baz = 1;
}
getBaz() { return this.baz}
} };
sinon.stubConstructor = function(constructor, fake) {
return sinon.spy((...args) => { // alternatively: sinon.stub().callsFake(..)
var i = Object.create(constructor.prototype);
fake.apply(i, args);
return i;
})
}
var stubbedConstructor = sinon.stubConstructor(foo.Bar, function() {
this.baz = 42;
});
console.log('Tests on using the stubbed constructor')
var myBar = new stubbedConstructor();
console.log('instanceof', myBar instanceof foo.Bar); // ==> true
console.log('this.getBaz()', myBar.getBaz()); // ==> 42
new stubbedConstructor();
new stubbedConstructor();
console.log('Call count', stubbedConstructor.callCount); // ==> 3 Not totally sure about the If this is what people wants, then I could supply the PR, but the name is just a suggestion. What do you think, @mroderick? |
To add my own thoughts; I was trying to fix a bug where calling an es6 class constructor without 'new' would throw. After looking at the source I realized the proxy was not calling the original in the exact same way the proxy gets called in the test and to me created a discrepancy. I want my original to be run identically to how I ran the proxy. |
@fatso83 More or less. The use of
I guess this still doesn't solve the problem completely; |
No, it wouldn't. At least without much custom hacking, reproducing existing code, as we can't really use the stub for much, hence using a spy. This would basically cover the 80/20 case, not getting all details right, but still addressing the issues of the most common needs. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
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 sinonjs#1265
Currently spies and stubs don't call original or stub function with
new
by design - even if they were called withnew
. The suggestion is to add this behaviour to them.To my knowledge, some of the cases could be easily treated with
createStubInstance
, while in other cases it will be difficult. SincecreateStubInstance
creates an instance, a wrapper function should be created manually, and if there should be static methods, they should be created manually too. If test case presumes that wrapper function should be called with or withoutnew
, this should be coded manually too.I believe that doing this in
sinon.spy
andsinon.stub
would result in more consistent behaviour.What did you expect to happen?
I would expect that something like this will happen inside a spy/stub:
Code
What actually happens
Original spied/stubbed classes and constructor function aren't called with
new
. This includes ES6 classes that were transpiled with Babel and have a safeguard against being called directly. This results in error:How to reproduce
The text was updated successfully, but these errors were encountered: