<p>sinon.restore () &amp;&amp; sandbox.restore () stellt keine Fälschungen wieder her</p>

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

Beschreibe den Fehler
Fälschungen sinon.restore() können nicht gelöscht werden (noch resetHistory , resetBehavior oder reset ). Ich habe dann versucht, eine neue Sandbox zu erstellen und die Sandbox zu löschen. Kein Würfel. Ist das beabsichtigt?

Fortpflanzen

it("Demonstrates how to restore a fake", () => {
  let sandbox = sinon.createSandbox();
  let thing = sandbox.fake();
  thing("Hi");
  expect(thing.calledOnce).to.be.true;
  expect(thing.lastArg).to.equal("Hi");
  sandbox.restore();
  sandbox.resetHistory();
  sandbox.resetBehavior();
  sandbox.reset();
  expect(thing.calledOnce).to.be.false; // Fails. thing.calledOnce === true
  expect(thing.lastArg).to.be.undefined; // Fails if above commented out. thing.lastArg === "Hi"
});

Erwartetes Verhalten
Ich habe erwartet, dass thing.lastArg entweder undefined oder null . Es gibt mir "Hi"

Screenshots
N / A

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

  • Bibliotheksversion: Sinon ^ 7.3.2
  • Umgebung: Knoten 10.16.0
  • Beispiel-URL: N / a
  • Andere Bibliotheken, die Sie verwenden: Mocha, Chai

Zusätzlicher Kontext
Testen Sie einfach die Funktionen von Sinon, während ich damit ein Backend teste.

Bug Help wanted

Hilfreichster Kommentar

Fair genug - danke für die Erklärung.

Am Fr, 19. Februar 2021 um 7:02 Uhr Carl-Erik Kopseng [email protected]
schrieb:

@scottpatrickwright https://github.com/scottpatrickwright Es ist geschlossen
weil es keinen Fehler gibt, wie aus dem Thread ersichtlich sein sollte. Es war nur
Benutzerfehler, wie in Ihrem Fall: Es funktioniert wie beschrieben und beabsichtigt :-)

Der Sinon-Sandkasten kann Dinge aufräumen, über die er Bescheid weiß. Das heißt, Sinon hat
Kenntnis von den Objekten haben, mit denen es interagiert. Der Stummel dich
oben beschrieben ist eigenständig gemacht. Sinon wird auf keines der Dinge aufmerksam gemacht
Objekte, denen Sie es zuweisen. Das ändert sich im zweiten Beispiel. Du könntest
Führen Sie auch sinon.replace (obj, fieldname, fake) aus, um dasselbe zu erreichen. Es ist nur
JavaScript 🙂

- -
Sie erhalten dies, weil Sie erwähnt wurden.
Antworte direkt auf diese E-Mail und sieh sie dir auf GitHub an
https://github.com/sinonjs/sinon/issues/2065#issuecomment-782032440 oder
Abmelden
https://github.com/notifications/unsubscribe-auth/AAKKRTFVMGEYVIB5GSIDXKTS7ZHMRANCNFSM4IGBASQQ
.

Alle 16 Kommentare

So wie es ist, sieht es aus wie ein Fehler, aber um ehrlich zu sein, bin ich mir da nicht ganz sicher. Ich erinnere mich, dass ein wichtiger Punkt bei Fälschungen ist, dass sie in gewissem Sinne unveränderlich sein sollten, aber da sie einen Zustand haben (dh sie wissen, ob sie gerufen wurden), muss diese Unveränderlichkeit nur auf das Stubbing-Verhalten beschränkt sein, nehme ich an.

@mroderick könnte die richtige Person sein, um dies zu beantworten ...

Wenn dies das richtige Verhalten ist, sollten wir zumindest die Dokumente aktualisieren.

@ fatso83 Sehr geschätzt! Das .restore doc erwähnte Fälschungen:

image

von hier .

War nur ein bisschen von diesem Fehler selbst, also wäre es schön, das zu beheben.

Wenn in den nächsten Tagen niemand anderes eine PR dafür macht, kann ich sehen, ob ich die Zeit finde, das Problem zu beheben

Ich habe mir das jetzt angesehen und die Dokumente sind etwas irreführend, ebenso wie der obige Test. Es scheint tatsächlich (fast) das zu tun, was es sagt, aber definieren wir zuerst einige Begriffe:

Wiederherstellen - Wenn Sie eine Sandbox wiederherstellen, werden alle Stubbed-Funktionen in ihrem ursprünglichen Zustand wiederhergestellt. Dies bedeutet, dass die Stubs von jedem Objekt entfernt werden, wenn sie das Original überschrieben haben.
Zurücksetzen - Zurücksetzen bedeutet, dass der Status jeder der erstellten Fälschungen gelöscht wird, diese jedoch weiterhin auf den Objekten vorhanden sind.

Das Problem mit dem obigen Test ist, dass es

  1. Entfernt alle Fälschungen aus dem Sandkasten
  2. Anschließend wird die Sammlung von Fälschungen in der Sandbox (jetzt leer) durchgearbeitet und versucht, die (leere) Liste der Fälschungen zurückzusetzen

Das macht keinen Sinn :-)

Ich habe getestet und sowohl die Anrufe reset als auch restore funktionieren wie sie sollten. Fast ... reset bereinigt den Status von calledOnce , aber lastArgument scheint nicht gelöscht zu werden. Überprüfen Sie etwas mehr, um festzustellen, ob ich einige Details verloren habe.

Das Schließen als nicht reproduzierbar, aber das Öffnen einer neuen Ausgabe des Fehlers fake.lastArg .

Zur Überprüfung: https://runkit.com/fatso83/sinon-issue-2065

Ich kann bestätigen, dass dieser Fehler auch bei mir auftritt. Ich habe ein Testszenario, bei dem die Implementierung intakt sein muss, aber die Funktion enthält das Stub-Ergebnis eines vorherigen Tests, was bedeutet, dass sandbox.restore() nicht das tut, was beabsichtigt zu tun.

Dies passiert mir in Version 7.5.0

@ oscarr-reyes Können Sie überprüfen, ob https://github.com/sinonjs/sinon/commit/54df7f7000a9db2dd05319daa49518f3cd5a5dd7 das Problem für Sie behebt? Ich denke, es hat es noch nicht in eine neue Version geschafft.

@ oscarr-reyes Können Sie ein reproduzierbares Beispiel machen? Wir haben diesen Fehler noch nicht gesehen. Wenn Sie sich den Thread oben und meine Erklärung ansehen, werden Sie sehen, dass der einzige Fehler, den wir gefunden haben, darin bestand, dass eine einzelne Flagge nicht gelöscht wurde. Alles andere funktioniert. Wenn wir also keinen Beweis sehen, gibt es keinen Fehler (abgesehen von der lastArg-Flagge).

Ich habe das gleiche Problem.

Ich habe eine Sandbox für meine Middleware "validateCaptcha" und wenn ich sie wiederherstelle, wird weiterhin der Stub ausgegeben.

/src/middlewares/captcha.js

const request = require("got");

const validateCaptcha = async (req, res, next) => {
    // if (process.env.NODE_ENV !== "production") return next();

    const captcha = req.body["g-recaptcha-response"] || req.body.g_recaptcha_response;

    // g-recaptcha-response is the key that browser will generate upon form submit.
    // if its blank or null means user has not selected the captcha, so return the error.
    if (captcha === undefined || captcha === "" || captcha === null)
        return res
            .status(400)
            .json({ message: "Please, verify that you are not a robot" });

    // Put your secret key here.
    const secretKey = process.env.GOOGLE_CAPTCHA_API_SECRET_KEY;

    // req.connection.remoteAddress will provide IP address of connected user.
    const verificationUrl = `https://www.google.com/recaptcha/api/siteverify?secret=${secretKey}&response=${captcha}`;

    try {

        // Hitting GET request to the URL, Google will respond with success or error scenario.
        const { body } = await request.post(verificationUrl, { responseType: "json" });

        // Success will be true or false depending upon captcha validation.
        if (body.success !== undefined && !body.success)
            return res
                .status(400)
                .json({ message: "Captcha validation error" });
    } catch (error) {
        return res
            .status(503)
            .json({ message: "Couldn't validate captcha" });
    }

    next();
};

module.exports = {
    validateCaptcha,
};

/test/api/user.spec.js

require("../setup.spec");
const supertest = require("supertest");
const captcha = require("../../src/middlewares/captcha");
const sinon = require("sinon");
let app;
let agent;
let sandbox;

const login = (anAgent, userCredentials) =>
    anAgent
        .post("/api/users/signIn")
        .send(userCredentials);

const logout = (anAgent) =>
    anAgent
        .post("/api/users/signOut");

describe("User endpoints", function () {
    this.beforeAll(async () => {
        sandbox = sinon.createSandbox();
        sandbox
            .stub(captcha, "validateCaptcha")
            .callsFake(async (req, res, next) => {
                console.log("Validate Captcha FAKE");
                return next();
            });
        // sandbox.restore();
    });

    this.beforeEach(async () => {
        app = require("../../src/app");
        agent = supertest.agent(app);
        const sequelize = require("../../src/models");
        await sequelize.sync({ force: true });

        const Customer = require("../../src/models/customer");
        const User = require("../../src/models/user");
        await Customer.create(
            {
                firstName: "Test",
                lastName: "Customer",
                user: {
                    email: "[email protected]",
                    password: "boo",
                },
            },
            {
                include: [User],
            }
        );
    });

    this.afterEach(async () => {
        sandbox.restore();
    });

    it("should create a new user", function (done) {
        agent
            .post("/api/users/signUp")
            .send({
                firstName: "firstName",
                lastName: "lastName",
                email: "[email protected]",
                password: "aPassword",
            })
            .expect(201)
            .end((err, res) => {
                err ? done(err) : done();
            });
    });

    it("should sign in", function (done) {
        login(agent, { email: "[email protected]", password: "boo" })
            .expect(200)
            .end((err, res) => {
                const { message, user } = res.body;
                message.should.be.equal("valid");
                user.should.have.property("email").equal("[email protected]");
                user.should.have.property("customer").have.property("firstName").equal("Test");
                user.should.have.property("customer").have.property("lastName").equal("Customer");

                agent
                    .get("/api/users/me")
                    .expect(200)
                    .end((err, res) => {
                        const user = res.body;
                        user.should.have.property("email").equal("[email protected]");
                        user.should.have.property("customer").have.property("firstName").equal("Test");
                        user.should.have.property("customer").have.property("lastName").equal("Customer");
                        err ? done(err) : done();
                    });
            });
    });

    it("should sign out", async function () {
        await login(agent, { email: "[email protected]", password: "boo" });
        await logout(agent)
            .expect(302)
            .expect("Location", "/");

        return agent
            .get("/api/users/me")
            .expect(401);
    });

    it("should return unauthorized", function (done) {
        agent
            .get("/api/users/me")
            .expect(401)
            .end((err, res) => {
                err ? done(err) : done();
            });
    });
});

Was ich tue, um zu überprüfen, ob es nicht funktioniert, ist:
1) Verspotten Sie es für den ersten Test
2) Stellen Sie es für die folgenden wieder her

In beforeAll gibt es einen Kommentar "sandbox.restore ();" dass ich es versucht habe und dort hat es funktioniert ... aber es ist nutzlos

Ich benötige außerdem jedes Mal meine app.js.

Vor fünf Minuten habe ich es geändert zu:

require("../setup.spec");
const decache = require("decache");
const supertest = require("supertest");
const sequelize = require("../../src/models");

const sinon = require("sinon");
const sandbox = sinon.createSandbox();
let agent;

const login = (anAgent, userCredentials) =>
    anAgent
        .post("/api/users/signIn")
        .send(userCredentials);

const logout = (anAgent) =>
    anAgent
        .post("/api/users/signOut");

describe("User endpoints", function () {
    this.beforeAll(async () => {

    });

    this.beforeEach(async () => {
        decache("../../src/app");
        decache("../../src/middlewares/captcha");

        const captcha = require("../../src/middlewares/captcha");

        sandbox
            .stub(captcha, "validateCaptcha")
            .callsFake(async (req, res, next) => {
                console.log("Validate Captcha FAKE");
                return next();
            });

        const app = require("../../src/app");
        agent = supertest.agent(app);
        await sequelize.sync({ force: true });


        const Customer = require("../../src/models/customer");
        const User = require("../../src/models/user");
        await Customer.create(
            {
                firstName: "Test",
                lastName: "Customer",
                user: {
                    email: "[email protected]",
                    password: "boo",
                },
            },
            {
                include: [User],
            }
        );
    });

    this.afterEach(async () => {
        sandbox.restore();
    });

    it("should create a new user", function (done) {
        agent
            .post("/api/users/signUp")
            .send({
                firstName: "firstName",
                lastName: "lastName",
                email: "[email protected]",
                password: "aPassword",
            })
            .expect(201)
            .end((err, res) => {
                err ? done(err) : done();
            });
    });

    it("should sign in", function (done) {
        login(agent, { email: "[email protected]", password: "boo" })
            .expect(200)
            .end((err, res) => {
                const { message, user } = res.body;
                message.should.be.equal("valid");
                user.should.have.property("email").equal("[email protected]");
                user.should.have.property("customer").have.property("firstName").equal("Test");
                user.should.have.property("customer").have.property("lastName").equal("Customer");

                agent
                    .get("/api/users/me")
                    .expect(200)
                    .end((err, res) => {
                        const user = res.body;
                        user.should.have.property("email").equal("[email protected]");
                        user.should.have.property("customer").have.property("firstName").equal("Test");
                        user.should.have.property("customer").have.property("lastName").equal("Customer");
                        err ? done(err) : done();
                    });
            });
    });

    it("should sign out", async function () {
        await login(agent, { email: "[email protected]", password: "boo" });
        await logout(agent)
            .expect(302)
            .expect("Location", "/");

        return agent
            .get("/api/users/me")
            .expect(401);
    });

    it("should return unauthorized", function (done) {
        agent
            .get("/api/users/me")
            .expect(401)
            .end((err, res) => {
                err ? done(err) : done();
            });
    });
});

Ich sehe auch dieses Problem. Warum ist das geschlossen?

Möglicherweise hängt das Verhalten der Wiederherstellung von der spezifischen Syntax ab, die zum Einrichten des Stubs verwendet wird. Afaik beide sollten gültige Methoden sein, aber die restore () ist anders. In einem funktioniert es und in dem anderen hat es unerwartete Ergebnisse.

const sinon = require('sinon')

// restore does not work as expected

let db = {
  query: () => {
    return 'my query 1'
  }
}
const dbStub = sinon.stub().resolves('somejson')
db.query = dbStub
db.query() // somejson
sinon.restore()
db.query() // resolves nothing

// restore works as expected

db = {
  query: () => {
    return 'my query 1'
  }
}
sinon.stub(db, 'query').resolves('somejson')
db.query() // somejson
sinon.restore()
db.query() //my query 1

@scottpatrickwright Wenn Sie Zuweisungen direkt an db.query vornehmen, kann sinon nicht wissen, was wiederhergestellt werden muss oder wie hoch der Wert vor der Zuweisung war.

@scottpatrickwright Es ist geschlossen, weil es keinen Fehler gibt, wie aus dem Thread ersichtlich sein sollte. Es war nur ein Benutzerfehler, wie in Ihrem Fall: Es funktioniert wie beschrieben und beabsichtigt :-)

Der Sinon-Sandkasten kann Dinge aufräumen, über die er Bescheid weiß. Das bedeutet, dass Sinon die Objekte kennen muss, mit denen es interagiert. Der oben beschriebene Stub ist eigenständig. Sinon wird auf keines der Objekte aufmerksam gemacht, denen Sie es zuweisen. Das ändert sich im zweiten Beispiel. Sie können auch sinon.replace(obj, fieldname, fake) tun, um dasselbe zu erreichen. Es ist nur JavaScript 🙂

Fair genug - danke für die Erklärung.

Am Fr, 19. Februar 2021 um 7:02 Uhr Carl-Erik Kopseng [email protected]
schrieb:

@scottpatrickwright https://github.com/scottpatrickwright Es ist geschlossen
weil es keinen Fehler gibt, wie aus dem Thread ersichtlich sein sollte. Es war nur
Benutzerfehler, wie in Ihrem Fall: Es funktioniert wie beschrieben und beabsichtigt :-)

Der Sinon-Sandkasten kann Dinge aufräumen, über die er Bescheid weiß. Das heißt, Sinon hat
Kenntnis von den Objekten haben, mit denen es interagiert. Der Stummel dich
oben beschrieben ist eigenständig gemacht. Sinon wird auf keines der Dinge aufmerksam gemacht
Objekte, denen Sie es zuweisen. Das ändert sich im zweiten Beispiel. Du könntest
Führen Sie auch sinon.replace (obj, fieldname, fake) aus, um dasselbe zu erreichen. Es ist nur
JavaScript 🙂

- -
Sie erhalten dies, weil Sie erwähnt wurden.
Antworte direkt auf diese E-Mail und sieh sie dir auf GitHub an
https://github.com/sinonjs/sinon/issues/2065#issuecomment-782032440 oder
Abmelden
https://github.com/notifications/unsubscribe-auth/AAKKRTFVMGEYVIB5GSIDXKTS7ZHMRANCNFSM4IGBASQQ
.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen