Sinon: Test nach Version 7.2.0 unerwartet fehlgeschlagen

Erstellt am 23. Juli 2019  ·  11Kommentare  ·  Quelle: sinonjs/sinon

Beschreibe den Fehler
Das Upgrade von Sinon auf die neueste Version 7 führt zu unerwarteten Fehlern. Die einzige relevante Änderung, die ich identifizieren konnte, war diese PR: # 1955 - Ersetzen von deep-equal.js durch samsam.deepEqual .
Die Tests bestehen alle Versionen bis 7.2.0. Das Zurücksetzen auf 7.1.1 (eine Version zurück) verursacht keine Probleme und alle Tests bestehen.

Beobachteter Fehler:

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

Testproduktionsfehler:

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

Fortpflanzen
Schritte zum Reproduzieren des Verhaltens:

  1. Verwenden Sie eine beliebige Sinon-Version über 7.1.1
  2. Probentest durchführen (oben)
  3. Siehe Fehler

Erwartetes Verhalten
Test sollte bestehen

Screenshots
Fügen Sie gegebenenfalls Screenshots hinzu, um Ihr Problem zu erklären.

Kontext (bitte vervollständigen Sie die folgenden Informationen):

  • Bibliotheksversion: 7.2.0+
  • Umgebung: macOS 10.14.5

Bitte lassen Sie mich wissen, ob ich weitere Informationen dazu liefern kann.

Bug Regression pinned

Hilfreichster Kommentar

Hi @ fatso83 ,

Vielen Dank, dass Sie sich die Zeit genommen haben, sich damit zu befassen. Ich habe getan, was Sie von mir verlangt haben, und eine Runkit-Demo erstellt, die den Fehler zeigt. Kommentieren / kommentieren Sie einfach die verschiedenen require('sinon') -Anweisungen und führen Sie den Code aus, um den Fehler zu sehen.

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

Ich poste den Code auch hier, falls das Runkit aus irgendeinem Grund nicht funktioniert.

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

Bitte schauen Sie noch einmal, wenn Sie Zeit haben. Vielen Dank.

Mit freundlichen Grüßen,
Daniel

Alle 11 Kommentare

Vielen Dank für einen allgemein großartigen Fehlerbericht. Es hat jedoch ein großes Defizit: Ich kann Ihr Beispiel nicht ausführen, um den Fehler zu überprüfen oder aufzuspüren! Es kann nicht alleine ausgeführt werden, und ohne eine Möglichkeit zur Reproduktion ist es schwierig, dies zu beheben.

Könnten Sie einen minimalen Kandidaten für die Reproduktion machen? Sie müssen nicht das gesamte Originalbeispiel replizieren, sondern eher eine Vereinfachung wie var myObject = { aMethod: function(){}, aProp: 42 }; // etc .

Wenn wir gewusst hätten, dass dies nicht funktioniert, hätten wir natürlich die Hauptversion verbessert, also wäre ein Regressionstest großartig!

PS Scheint, als wäre auch sinon-chai beteiligt. Das ist eine Auflistung wert.

@ fatso83 Lassen Sie mich sehen, wie ich ein isoliertes, lauffähiges Beispiel für die Reproduktion erhalten kann

Irgendwelche Updates?

Dieses Problem wurde automatisch als veraltet markiert, da es in letzter Zeit keine Aktivitäten gab. Es wird geschlossen, wenn keine weitere Aktivität stattfindet. Vielen Dank für Ihre Beiträge.

@mantoni Hast du nicht berichtet, dass so etwas in einem deiner Projekte passiert ist?

Entschuldigung für den Mangel an Updates, ich bin nicht mehr mit dem Projekt verbunden, das das Problem enthielt. Wenn jemand anderes das gleiche Problem hat, wäre es großartig, wenn er ein Beispiel für Repro liefern könnte

@ fatso83 Ich kann mich nicht erinnern, gestoßen bin. Ich habe in einigen Projekten ohne Probleme auf das neueste Sinon aktualisiert.

Schließen als kann nicht reproduzieren

Es tut mir leid, dass ich dieses Problem von den Toten wiederbelebt habe, aber ich habe das gleiche Problem.

Der folgende Code ist zur Veranschaulichung vereinfacht.

In meiner Bewerbung habe ich diese Klasse

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

und ich benutze es später in einer Koa-Controller-Funktion wie dieser

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

Und in meinem getUserDetailsController.test.js mache ich so etwas:

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

Ich habe dies mit sinon 7.1.1 getestet (das "2.1.3" von samsam ), und das funktioniert.
Version 7.2.0 schlägt fehl (verwendet 3.3.3 von samsam ).
Die neueste Version 9.2.3 schlägt ebenfalls fehl (verwendet 5.3.0 von samsam ).

Ich bin auf Knoten 14.5.3, aber dies passiert auch auf Knoten 12.20.0.

Ich habe die user im Controller und die expectedUser im Test manuell über JSON.stringify verglichen und sie sind 100% gleich. Der einzige syntaktische Unterschied besteht darin, dass der Controller die Klasse verwendet, während der Test ein Objektliteral verwendet.

Hat jemand eine gute Idee, warum das passiert? Oder hat jemand eine gute Idee, wie man das umgehen kann?

Mit freundlichen Grüßen,
Daniel

Solange wir keinen reproduzierbaren Fall haben, um dies zu überprüfen, können wir es leider nicht rechtfertigen, unsere freien Stunden damit zu verbringen, dies zu untersuchen. Ich hätte nichts zu suchen und nichts zu überprüfen, ob ich Recht hatte.

Ich liebe es jedoch, Fehler zu beheben. Wenn Sie also einige Zeit damit verbringen können, etwas zu machen, das ich ausführen kann, tun Sie dies! RunKit ist dafür ein großartiger Service: https://runkit.com/fatso83/sinon-issue-reproducible-bug-template

Hi @ fatso83 ,

Vielen Dank, dass Sie sich die Zeit genommen haben, sich damit zu befassen. Ich habe getan, was Sie von mir verlangt haben, und eine Runkit-Demo erstellt, die den Fehler zeigt. Kommentieren / kommentieren Sie einfach die verschiedenen require('sinon') -Anweisungen und führen Sie den Code aus, um den Fehler zu sehen.

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

Ich poste den Code auch hier, falls das Runkit aus irgendeinem Grund nicht funktioniert.

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

Bitte schauen Sie noch einmal, wenn Sie Zeit haben. Vielen Dank.

Mit freundlichen Grüßen,
Daniel

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen