Sinon: Uji tiba-tiba gagal setelah rilis v7.2.0

Dibuat pada 23 Jul 2019  ·  11Komentar  ·  Sumber: sinonjs/sinon

Jelaskan bugnya
Mengupgrade Sinon ke rilis v7 terbaru menyebabkan beberapa kegagalan yang tidak terduga. Satu-satunya perubahan relevan yang dapat saya identifikasi adalah PR ini: # 1955 - Mengganti deep-equal.js dengan samsam.deepEqual .
Tes meneruskan semua versi hingga 7.2.0, kembali ke 7.1.1 (satu rilis kembali) tidak menyebabkan masalah apa pun dan semua tes lulus.

Kesalahan Teramati:

AssertionError: expected addTracks to have been called with arguments [{ language: "en", trackContentType: "CEA608" }]
[[functionStub] { language: "en", trackContentType: "CEA608" }] [{ language: "en", trackContentType: "CEA608" }]

Uji Kesalahan Produksi:

    it('should call getTextTracksManager, Track, and setCaptionLang', () => {
      sinonSandbox.stub(chromecastReceiver, 'setCaptionLang');
      chromecastReceiver.player.getTextTracksManager = sinonSandbox.stub()
        .returns({ addTracks: sinonSandbox.spy() });
      sinonSandbox.stub(cast.framework.messages, 'Track').returns(() => ({}));

      chromecastReceiver.loadCaptions('off');

      expect(chromecastReceiver.player.getTextTracksManager).to.have.callCount(1);
      expect(cast.framework.messages.Track).to.have.been
        .calledWith(3, cast.framework.messages.TrackType.TEXT);
      expect(chromecastReceiver.textTracksManager.addTracks).to.have.been.calledWith([{
        trackContentType: cast.framework.messages.CaptionMimeType.CEA608,
        language: 'en',
      }]);
      expect(chromecastReceiver.setCaptionLang).to.have.been.calledWith('off');
    });

Untuk Mereproduksi
Langkah-langkah untuk mereproduksi perilaku:

  1. Gunakan versi Sinon apa pun di atas 7.1.1
  2. Jalankan uji sampel (di atas)
  3. Lihat kesalahan

Perilaku yang diharapkan
Tes harus lulus

Screenshot
Jika memungkinkan, tambahkan tangkapan layar untuk membantu menjelaskan masalah Anda.

Konteks (lengkapi informasi berikut):

  • Versi perpustakaan: 7.2.0+
  • Lingkungan: macOS 10.14.5

Tolong beri tahu saya jika saya dapat memberikan informasi lebih lanjut tentang ini.

Bug Regression pinned

Komentar yang paling membantu

Hai @ fatso83 ,

Terima kasih telah meluangkan waktu Anda untuk memeriksanya. Saya melakukan apa yang Anda minta dan membuat demo runkit yang menunjukkan bug. Cukup beri komentar / hapus komentar pada pernyataan require('sinon') yang berbeda dan jalankan kode untuk melihat bug.

https://runkit.com/danielkg/sinon-issue-reproducible-bug-template

Saya memposting kode di sini juga jika runkit tidak berfungsi karena alasan apa pun.

// Employs 'mini-mocha' to emulate running in the Mocha test runner (mochajs.org)
require("@fatso83/mini-mocha").install();
// const sinon = require('[email protected]'); // WORKS!
const sinon = require('[email protected]'); // FAILS!
// const sinon = require('sinon');       // FAILS!
const { assert } = require('@sinonjs/referee');

const SAMPLE_USER = {
    id: 1,
    name: 'Kid',
    age: 22,
    weight: 83.5,
    notes: [{ txt: 'abc' }, { txt: 'def' }, { txt: 'ghi' }],
};

class MyUser {
    constructor(id, name, age, weight, notes = []) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.weight = weight;
        this.notes = notes;
    }
}

const createFakeUser = overrides => ({
    id: '007',
    name: 'Bond',
    ...overrides,
});

class Talkie {
    talk(user, topic) {
        console.log('talked to', user.name, 'about', topic);
    }
}

const action = (userId, talkie) => {
    const { name, age, weight, notes } = SAMPLE_USER;
    const user = new MyUser(userId, name, age, weight, notes);

    talkie.talk(user, 'apples');

    return user;
}


describe('stubbing', () => {
    const talkie = new Talkie();

    afterEach(() => {
        sinon.restore();
    });

    beforeEach(() => {
        sinon.spy(talkie, 'talk');
    });

    it('is the same user', () => {
        const userA = action(1, talkie);
        const userB = createFakeUser(SAMPLE_USER);

        assert.equals(JSON.stringify(userA), JSON.stringify(userB));
    });

    it('should set the return value', () => {
        const userA = action(1, talkie);
        const userB = createFakeUser(SAMPLE_USER);

        sinon.assert.calledWith(talkie.talk, userB, sinon.match.string);
    });
});

Silakan lihat lagi ketika Anda punya waktu. Terima kasih.

Salam,
Daniel

Semua 11 komentar

Terima kasih atas laporan bug yang umumnya bagus. Namun, ada satu kekurangan utama: Saya tidak dapat menjalankan contoh Anda untuk verifikasi atau melacak bug! Ini tidak dapat dijalankan dengan sendirinya, dan tanpa cara mereproduksi, sulit untuk memperbaikinya.

Bisakah Anda membuat kandidat minimal untuk reproduksi? Anda tidak perlu mereplikasi seluruh contoh asli, lebih seperti penyederhanaan seperti var myObject = { aMethod: function(){}, aProp: 42 }; // etc .

Jika kami tahu ini rusak, kami tentu saja akan menaikkan versi mayor, jadi uji regresi akan sangat bagus!

PS Sepertinya sinon-chai juga terlibat. Itu layak untuk dicantumkan.

@ fatso83 Biarkan saya melihat bagaimana saya bisa mendapatkan contoh yang terisolasi dan dapat dijalankan untuk reproduksi

Ada pembaruan?

Masalah ini secara otomatis ditandai sebagai usang karena tidak ada aktivitas terbaru. Ini akan ditutup jika tidak ada aktivitas lebih lanjut. Terima kasih atas kontribusi Anda.

@mantoni Bukankah Anda melaporkan mengalami hal seperti ini terjadi di salah satu proyek Anda?

Maaf atas kurangnya pembaruan, saya tidak lagi terkait dengan proyek yang mengandung masalah tersebut. Jika ada orang lain yang mengalami masalah yang sama, alangkah baiknya jika mereka dapat memberikan contoh untuk repro

@ fatso83 Saya tidak ingat pernah mengalami masalah yang sama. Saya telah meningkatkan ke Sinon terbaru dalam beberapa proyek tanpa masalah apa pun.

Menutup karena tidak dapat mereproduksi

Maaf telah menghidupkan kembali masalah ini dari kematian, tetapi saya mengalami masalah yang sama.

_Kode di bawah ini disederhanakan untuk tujuan ilustrasi._

Dalam aplikasi saya, saya memiliki kelas ini

class MyUser {
  // ... some user properties  
}

dan saya menggunakannya nanti dalam fungsi pengontrol Koa seperti ini

const mqClient = require('./mqClient');

// GET /userDetails/<id> endpoint
async function getUserDetailsController(req, res) {
  const user = new MyUser();

  // populate user with properties etc.
  user.id = '1';
  user.name = 'Hans Gruber';
  user.tasks = [{ id: '42', title: 'execute Nakatomi tower heist' }];

  // ... get more details ...

  // Notify other users about this user
  mqClient.notifyOthers(user);

  res.json({ ok: true, user });
}

Dan di getUserDetailsController.test.js saya, saya melakukan sesuatu seperti ini:

const mqClient = require('./mqClient');

const createExpectedUser = overrides => {
  id: '1',
  name: 'Hans Gruber',
  tasks: [{ id: '42', title: 'execute Nakatomi tower heist' }],
  ...overrides
};

it('does not fail', async () => {
  sinon.spy(mqClient, 'notifyOthers');

  const expectedUser = createExpectedUser();

  await presetRequest // helper object to run the controller code
    .get('/userDetails/1')
    .expect(200);

  // This works with sinon 7.1.1.
  // This fails with sinon 7.2.0 and onwards.
  sinon.assert.calledWithMatch(mqClient.notifyOthers, expectedUser);
});

Saya menguji ini dengan sinon 7.1.1 (yang menggunakan "2.1.3" dari samsam ), dan berhasil.
Versi 7.2.0 gagal (menggunakan 3.3.3 dari samsam ).
Versi terbaru 9.2.3 juga gagal (menggunakan 5.3.0 dari samsam ).

Saya menggunakan Node 14.5.3, tetapi ini juga terjadi di Node 12.20.0.

Saya membandingkan user dalam pengontrol dan expectedUser dalam pengujian melalui JSON.stringify secara manual dan semuanya 100% sama. Satu-satunya perbedaan secara sintaksis adalah bahwa pengontrol menggunakan kelas, sedangkan pengujian menggunakan literal objek.

Adakah yang tahu mengapa ini terjadi? Atau apakah ada yang punya ide bagus tentang cara menyiasatinya?

Salam,
Daniel

Selama kami tidak memiliki kasus yang dapat direproduksi untuk memverifikasi ini, kami tidak dapat membenarkan menghabiskan waktu luang kami untuk menyelidiki ini, saya khawatir. Saya tidak akan memiliki apa pun untuk dicari dan tidak ada yang memverifikasi bahwa saya benar.

Saya suka memperbaiki bug, jadi jika Anda dapat meluangkan waktu untuk mencoba membuat sesuatu _Saya dapat berjalan_, lakukanlah! RunKit adalah layanan hebat untuk melakukannya: https://runkit.com/fatso83/sinon-issue-reproducible-bug-template

Hai @ fatso83 ,

Terima kasih telah meluangkan waktu Anda untuk memeriksanya. Saya melakukan apa yang Anda minta dan membuat demo runkit yang menunjukkan bug. Cukup beri komentar / hapus komentar pada pernyataan require('sinon') yang berbeda dan jalankan kode untuk melihat bug.

https://runkit.com/danielkg/sinon-issue-reproducible-bug-template

Saya memposting kode di sini juga jika runkit tidak berfungsi karena alasan apa pun.

// Employs 'mini-mocha' to emulate running in the Mocha test runner (mochajs.org)
require("@fatso83/mini-mocha").install();
// const sinon = require('[email protected]'); // WORKS!
const sinon = require('[email protected]'); // FAILS!
// const sinon = require('sinon');       // FAILS!
const { assert } = require('@sinonjs/referee');

const SAMPLE_USER = {
    id: 1,
    name: 'Kid',
    age: 22,
    weight: 83.5,
    notes: [{ txt: 'abc' }, { txt: 'def' }, { txt: 'ghi' }],
};

class MyUser {
    constructor(id, name, age, weight, notes = []) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.weight = weight;
        this.notes = notes;
    }
}

const createFakeUser = overrides => ({
    id: '007',
    name: 'Bond',
    ...overrides,
});

class Talkie {
    talk(user, topic) {
        console.log('talked to', user.name, 'about', topic);
    }
}

const action = (userId, talkie) => {
    const { name, age, weight, notes } = SAMPLE_USER;
    const user = new MyUser(userId, name, age, weight, notes);

    talkie.talk(user, 'apples');

    return user;
}


describe('stubbing', () => {
    const talkie = new Talkie();

    afterEach(() => {
        sinon.restore();
    });

    beforeEach(() => {
        sinon.spy(talkie, 'talk');
    });

    it('is the same user', () => {
        const userA = action(1, talkie);
        const userB = createFakeUser(SAMPLE_USER);

        assert.equals(JSON.stringify(userA), JSON.stringify(userB));
    });

    it('should set the return value', () => {
        const userA = action(1, talkie);
        const userB = createFakeUser(SAMPLE_USER);

        sinon.assert.calledWith(talkie.talk, userB, sinon.match.string);
    });
});

Silakan lihat lagi ketika Anda punya waktu. Terima kasih.

Salam,
Daniel

Apakah halaman ini membantu?
0 / 5 - 0 peringkat