Kesalahan Sinon Mencoba membungkus fungsi yang sudah dibungkus

92

Meskipun ada pertanyaan yang sama di sini tetapi saya tidak dapat menemukan jawaban untuk masalah saya, jadi inilah pertanyaan saya:

Saya menguji aplikasi node js saya menggunakan mocha dan chai. Saya menggunakan sinion untuk membungkus fungsi saya.

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
  });
}

Ketika saya mencoba menjalankan tes ini, saya mendapat kesalahan

Attempted to wrap getObj which is already wrapped

Saya juga mencoba menempatkan

beforeEach(function () {
  sandbox = sinon.sandbox.create();
});

afterEach(function () {
  sandbox.restore();
});

di setiap menjelaskan, tapi tetap memberi saya kesalahan yang sama.

Rohit Vyavahare
sumber
Anda dapat menemukan penjelasan di bagian bawah posting di sini
Nir Alfasi

Jawaban:

113

Anda harus mengembalikan fungsi getObjin after(), silakan coba seperti di bawah ini.

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();
    });
});
zangw
sumber
Setelah mencoba cara yang diterima di atas, saya mendapatkan kesalahan yang sama di bawah hook "sebelum semua"
Ashwin Hegde
@AshwinHegde, bisakah Anda memberi saya kode tes Anda? Mungkin saya dapat menemukan beberapa masalah di sini.
zangw
1
Apakah tidak ada cara untuk memulihkan semua rintisan tanpa menentukan masing-masing? Akan sangat bagus untuk memiliki sinon.restoreAll();yang dapat dijalankan setelah semua tes hanya untuk memastikan Anda tidak lupa untuk memulihkan sebuah rintisan.
Lukas
afterEach (() => {sinon.verifyAndRestore ();});
Sam T
20

Kesalahan ini karena tidak memulihkan fungsi rintisan dengan benar. Gunakan kotak pasir lalu buat rintisan menggunakan kotak pasir. Setelah setiap pengujian di dalam suite, pulihkan sandbox

  beforeEach(() => {
      sandbox = sinon.createSandbox();
      mockObj = sandbox.stub(testApp, 'getObj', fake_function)
  });

  afterEach(() => {
      sandbox.restore();
  });
Arjun Malik
sumber
1
Bung, selamatkan hidupku)
Yegor Zaremba
Ini berhasil untuk saya. Saya merasa ini harus menjadi jawaban yang diterima.
Daniel Kaplan
Saya memiliki beberapa tes dengan fungsi pembungkus dan perlu menggunakan afterEach .
Richard
Dalam kasus saya, ini adalah jawaban yang benar, karena saya memata-matai seluruh objek dan bukan metode tertentu, jadi saya tidak dapat memulihkan.
Edison Spencer
11

Untuk kasus di mana Anda perlu memulihkan semua metode dari satu objek, Anda dapat menggunakan sinon.restore(obj).

Contoh:

before(() => {
    userRepositoryMock = sinon.stub(userRepository);
});

after(() => {
    sinon.restore(userRepository);
});
Renan Ferreira
sumber
1
Ini tidak berhasil untuk saya saat mematikan fungsi pada objek. Saya harus mengembalikan per fungsi seperti jawaban yang diterima menunjukkan.
Ian Robertson
7
sinon.restore () tidak digunakan lagi di Sinon v2 dan dihapus setelahnya. // Previously sinon.restore(stubObject); // Typescript (stubObject as any).restore(); // Javascript stubObject.restore();
MatthiasSommer
6

Saya juga memukul ini menggunakan hook sebelum () dan sesudah () dari Mocha. Saya juga menggunakan pemulihan () seperti yang disebutkan di mana-mana. File pengujian tunggal berjalan dengan baik, beberapa tidak. Akhirnya ditemukan tentang Mocha root-level-hooks : Saya tidak memiliki sebelum () dan sesudah () di dalam saya sendiri menjelaskan (). Jadi, ia menemukan semua file dengan before () di tingkat root dan mengeksekusinya sebelum memulai pengujian apa pun.

Jadi, pastikan Anda memiliki pola yang serupa:

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');
  });
});
Wilfred Dittmer
sumber
3

Disarankan untuk menginisialisasi stub di 'beforeEach' dan memulihkannya di 'afterEach'. Tetapi jika Anda ingin bertualang, berikut ini juga berfungsi.

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();
  });
}
Karna
sumber
3

Bahkan dengan kotak pasir itu bisa memberi Anda kesalahan. Terutama saat pengujian dijalankan secara paralel untuk kelas ES6.

const sb = sandbox.create();

before(() => {
  sb.stub(MyObj.prototype, 'myFunc').callsFake(() => {
    return 'whatever';
  });
});
after(() => {
  sb.restore();
});

ini bisa menimbulkan kesalahan yang sama jika tes lain mencoba menghentikan myFunc dari Prototipe. Saya bisa memperbaikinya tetapi saya tidak bangga karenanya ...

const sb = sandbox.create();

before(() => {
  MyObj.prototype.myFunc = sb.stub().callsFake(() => {
    return 'whatever';
  });
});
after(() => {
  sb.restore();
});
Tonino
sumber
3

Bagi siapa pun yang mengalami masalah ini, jika Anda menghentikan atau memata-matai seluruh objek, dan kemudian Anda melakukannya

sandbox.restore ()

Anda masih akan mendapatkan error tersebut. Anda harus menghentikan / memata-matai metode individu.

Aku menyia-nyiakan selamanya untuk mencari tahu apa yang salah.

sinon-7.5.0

Khon Lieu
sumber
2

Saya mengalami ini dengan mata-mata. Perilaku ini membuat sinon sangat tidak fleksibel untuk diajak bekerja sama. Saya membuat fungsi pembantu yang mencoba menghapus mata-mata yang ada sebelum membuat yang baru. Dengan begitu saya tidak perlu khawatir tentang keadaan sebelum / sesudah. Pendekatan serupa mungkin juga berhasil untuk stub.

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);
};

Phil
sumber
0
function stub(obj, method) {
     // try to remove any existing stub in case it exists
      try {
        obj[method].restore();
      } catch (e) {
        // eat it.
      }
      return sinon.stub(obj, method);
    }

dan gunakan fungsi ini saat membuat stub dalam pengujian. Ini akan menyelesaikan kesalahan 'Kesalahan Sinon Mencoba membungkus fungsi yang sudah dibungkus'.

contoh:

stub(Validator.prototype, 'canGeneratePayment').returns(Promise.resolve({ indent: dTruckIndent }));
gramcha
sumber