node.js 诗农错误试图包装已经包装的函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36074631/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sinon error Attempted to wrap function which is already wrapped
提问by Rohit Vyavahare
Though there is a same question here but I could not find answer to my problem so here goes my question:
虽然这里有一个相同的问题,但我找不到我的问题的答案,所以我的问题是:
I am testing my node js app using mocha and chai. I am using sinion to wrap my function.
我正在使用 mocha 和 chai 测试我的节点 js 应用程序。我正在使用 sinion 来包装我的函数。
describe('App Functions', function(){
let mockObj = sinon.stub(testApp, 'getObj', (dbUrl) => {
//some stuff
});
it('get results',function(done) {
testApp.someFun
});
}
describe('App Errors', function(){
let mockObj = sinon.stub(testApp, 'getObj', (dbUrl) => {
//some stuff
});
it('throws errors',function(done) {
testApp.someFun
});
}
When I try to run this test it gives me error
当我尝试运行此测试时,它给了我错误
Attempted to wrap getObj which is already wrapped
I also tried putting
我也试过放
beforeEach(function () {
sandbox = sinon.sandbox.create();
});
afterEach(function () {
sandbox.restore();
});
in each describe, but still giving me same error.
在每个描述中,但仍然给我同样的错误。
回答by zangw
You should restore the getObjin after()function, please try it as below.
您应该恢复getObjinafter()功能,请尝试如下。
describe('App Functions', function(){
var mockObj;
before(function () {
mockObj = sinon.stub(testApp, 'getObj', () => {
console.log('this is sinon test 1111');
});
});
after(function () {
testApp.getObj.restore(); // Unwraps the spy
});
it('get results',function(done) {
testApp.getObj();
});
});
describe('App Errors', function(){
var mockObj;
before(function () {
mockObj = sinon.stub(testApp, 'getObj', () => {
console.log('this is sinon test 1111');
});
});
after( function () {
testApp.getObj.restore(); // Unwraps the spy
});
it('throws errors',function(done) {
testApp.getObj();
});
});
回答by Arjun Malik
This error is due to not restoring the stub function properly. Use sandbox and then create the stub using the sandbox. After the test suite restore the sandbox.
此错误是由于未正确恢复存根功能所致。使用沙箱,然后使用沙箱创建存根。在测试套件恢复沙箱之后。
before(() => {
sandbox = sinon.createSandbox();
mockObj = sandbox.stub(testApp, 'getObj', fake_function)
});
after(() => {
sandbox.restore();
});
回答by Renan Ferreira
For cases where you need to restore all the methods of one object, you can use the sinon.restore(obj).
对于需要恢复一个对象的所有方法的情况,可以使用sinon.restore(obj).
Example:
例子:
before(() => {
userRepositoryMock = sinon.stub(userRepository);
});
after(() => {
sinon.restore(userRepository);
});
回答by Wilfred Dittmer
I was also hitting this using the before() and after() hooks of Mocha. I was also using the restore() as mentioned everywhere. Single test file ran fine, multiple did not. Finally found about Mocha root-level-hooks: I did not have my before() and after() inside my own describe(). So it finds all files with before() at the root-level and executes those before starting any tests.
我也使用了 Mocha 的 before() 和 after() 钩子。我还使用了到处提到的 restore() 。单个测试文件运行良好,多个没有。终于找到了关于Mocha 根级挂钩:我自己的 describe() 中没有 before() 和 after()。因此,它会在根级别使用 before() 查找所有文件,并在开始任何测试之前执行这些文件。
So make sure you have a similar pattern:
所以确保你有一个类似的模式:
describe('my own describe', () => {
before(() => {
// setup stub code here
sinon.stub(myObj, 'myFunc').callsFake(() => {
return 'bla';
});
});
after(() => {
myObj.myFunc.restore();
});
it('Do some testing now', () => {
expect(myObj.myFunc()).to.be.equal('bla');
});
});
回答by Karna
It is advised to initialize stubs in 'beforeEach' and restore them in 'afterEach'. But in case you are feeling adventurous, the following works too.
建议在“beforeEach”中初始化存根并在“afterEach”中恢复它们。但是,如果您喜欢冒险,以下方法也适用。
describe('App Functions', function(){
let mockObj = sinon.stub(testApp, 'getObj', (dbUrl) => {
//some stuff
});
it('get results',function(done) {
testApp.someFun
mockObj .restore();
});
}
describe('App Errors', function(){
let mockObj = sinon.stub(testApp, 'getObj', (dbUrl) => {
//some stuff
});
it('throws errors',function(done) {
testApp.someFun
mockObj .restore();
});
}
回答by Tonino
Even with sandbox it could give you the error. Especially when tests run in parallel for ES6 classes.
即使使用沙箱,它也可能会给您带来错误。特别是当针对 ES6 类并行运行测试时。
const sb = sandbox.create();
before(() => {
sb.stub(MyObj.prototype, 'myFunc').callsFake(() => {
return 'whatever';
});
});
after(() => {
sb.restore();
});
this could throw the same error if another test is trying to stub myFunc from the Prototype. I was able to fix that but I am not proud of it...
如果另一个测试试图从原型中存根 myFunc,这可能会引发相同的错误。我能够解决这个问题,但我并不为此感到自豪......
const sb = sandbox.create();
before(() => {
MyObj.prototype.myFunc = sb.stub().callsFake(() => {
return 'whatever';
});
});
after(() => {
sb.restore();
});
回答by Khon
For anyone running into this issue, if you stub or spy on the entire object, and you later do
对于遇到此问题的任何人,如果您存根或监视整个对象,然后您
sandbox.restore()
沙盒.restore()
You'll still get the error. You have to stub/spy the individual methods.
你仍然会得到错误。您必须存根/监视各个方法。
I wasted forever trying to figure out what was wrong.
我浪费了永远试图找出问题所在。
sinon-7.5.0
sinon-7.5.0
回答by Phil
I ran into this with spies. This behaviour makes sinon pretty inflexible to work with. I created a helper function that attempts to remove any existing spy before setting a new one. That way I don't have to worry about any before/after state. A similar approach might work for stubs too.
我遇到了间谍。这种行为使 sinon 使用起来非常不灵活。我创建了一个辅助函数,尝试在设置新间谍之前删除任何现有的间谍。这样我就不必担心任何之前/之后的状态。类似的方法也可能适用于存根。
import sinon, { SinonSpy } from 'sinon';
/**
* When you set a spy on a method that already had one set in a previous test,
* sinon throws an "Attempted to wrap [function] which is already wrapped" error
* rather than replacing the existing spy. This helper function does exactly that.
*
* @param {object} obj
* @param {string} method
*/
export const spy = function spy<T>(obj: T, method: keyof T): SinonSpy {
// try to remove any existing spy in case it exists
try {
// @ts-ignore
obj[method].restore();
} catch (e) {
// noop
}
return sinon.spy(obj, method);
};

