See http://jsfiddle.net/8677e88e/
This can happen in a unit test, when we want to spy a function on the whole file (so in the outermost setup function), but stub only in a specific test.
The workaround is to restore the function before stubbing.
I think this is reasonnable, because the idea is to "upgrade" the spy into a stub.
The implementation is explicitly checking for this case and throwing a meaningful error (TypeError: Attempted to wrap func which is already wrapped). Personally, I wouldn't want any magic to happen in this case.
Yep the error is meaningful, and I actually think this is fine if the user tries to spy an existing spy or stub an existing stub, or even spy on an existing stub. All these cases are useless so it's ok to throw.
Yet I don't think it's magic to make a stub from a spy. A stub is a spy with more capabilities. Therefore calling "stub" on an existing spy would simply add these capabilities to the existing spy.
Ok, I understand. There's a few edge cases to think of, e.g. "downgrading" the stub back to a spy in sandbox restores. @cjohansen What do you think?
We can say that stubbing an existing spy in a different context (the spy was made with a sandbox while the stub is made without a sandbox or the contrary) is also forbidden (so same behavior than now).
You're sharing too much behavior. This is the desired Sinon behavior and will not change.
I'm disappointed to see this closed. This behavior makes it considerably more difficult to utilize sinon in legacy test suites.
I understand the logic. It's not desirable to have so much shared behavior for new test suites. But the first thing that needs done when attempting to refactor legacy test suites is introduce test doubles to create seams and begin to break things down to smaller unit tests. In such a scenario, this behavior is extremely frustrating to work around.
Also very disappointed by seeing this closed as it would be extremely useful in some test flows as following:
setting stubs with a success behavior in the root describe and then overriding one with a failing behavior into a nested describe.
@slecorvaisier : you can still do this, but you just have to be explicit about your intentions by restoring the original stub. you have to write an extra line of code, but you gain something by notifying the reader that overriding the stub implementation was your intent, IMHO.
@fatso83 : thanks for the input. As I completely understand your point of view, to me it seems obvious that I want to override the existing behavior (stub or original) when applying stub() on the method. Actually I want to notify that I need the method to be 'stubbed' at the end, whatever it was already stubbed or not before this action.
That being said, this is only my point of view and I totally understand the need to 'warn' another reader that this override is done on purpose. I'll go for the extra restore() call for now, and fork the project later.
Apologies for digging up an old issue, but I've just hit this and wondered if there's a recommended way to do what I want...
I'm stubbing methods in the VS Code API, such as vs.window.showWarningMessage so that tests can verify the correct messages are shown (and in some cases, respond to them by "clicking buttons" on those errors to check the handling).
I'm using Sinon sandboxes for each test so that any stubs are reset between tests. Everything works great!
However, I just came across a failing test on CI that is hard to diagnose - I think something is going wrong and a warning/error message is being shown (but they're not stubbed because I'm not specifically testing them).
My plan was to stub the showWarningMessage methods at a global level and make them write to the console (using callsFake) - so any un-intercepted messages for all tests will show up in their logs to help debug. The problem is that tests that do intercept them get this error.
What I hoped would happen, is that these would be "layered" so the sandbox is able to override methods that were already stubbed below the sandbox, and when the sandbox is restored, the behaviour went back to the "global" fake handler.
Is there a way to achieve this?
Most helpful comment
Also very disappointed by seeing this closed as it would be extremely useful in some test flows as following:
setting stubs with a success behavior in the root describe and then overriding one with a failing behavior into a nested describe.