<p>sinon.restore () &amp;&amp; sandbox.restore () tidak memulihkan palsu</p>

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

Jelaskan bugnya
Tidak dapat menghapus barang palsu sinon.restore() (atau resetHistory , resetBehavior , atau reset ). Saya kemudian mencoba membuat kotak pasir baru, dan mengosongkan kotak pasir. Tidak ada dadu. Apakah ini disengaja?

Untuk Mereproduksi

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

Perilaku yang diharapkan
Saya mengharapkan thing.lastArg menjadi undefined atau null . Ini memberi saya "Hi"

Screenshot
T / a

Konteks (lengkapi informasi berikut):

  • Versi perpustakaan: Sinon ^ 7.3.2
  • Lingkungan: Node 10.16.0
  • Contoh URL: T / a
  • Perpustakaan lain yang Anda gunakan: Mocha, Chai

Konteks tambahan
Hanya menguji kemampuan Sinon saat saya menggunakannya untuk menguji backend.

Bug Help wanted

Komentar yang paling membantu

Cukup adil - terima kasih atas penjelasannya.

Pada hari Jumat, 19 Feb 2021 pukul 07.02 Carl-Erik Kopseng [email protected]
menulis:

@scottpatrickwright https://github.com/scottpatrickwright Sudah ditutup
karena tidak ada bug, seperti yang terlihat dari utas. Itu hanya
kesalahan pengguna, seperti dalam kasus Anda: ini berfungsi seperti yang dijelaskan dan dimaksudkan :-)

Sandbox Sinon dapat membersihkan hal-hal yang diketahuinya. Itu artinya Sinon punya
untuk memiliki pengetahuan tentang objek yang berinteraksi dengannya. Rintisan Anda
uraikan di atas dibuat mandiri. Sinon tidak mengetahui apa pun dari
objek yang Anda tetapkan. Itu berubah pada contoh kedua. Anda bisa
juga lakukan sinon.replace (obj, fieldname, palsu) untuk mencapai hal yang sama. Hanya saja
JavaScript 🙂

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/sinonjs/sinon/issues/2065#issuecomment-782032440 , atau
berhenti berlangganan
https://github.com/notifications/unsubscribe-auth/AAKKRTFVMGEYVIB5GSIDXKTS7ZHMRANCNFSM4IGBASQQ
.

Semua 16 komentar

Karena memang _lihat seperti_ bug, tetapi jujur ​​saja, saya tidak sepenuhnya yakin tentang hal ini. Saya ingat poin kunci pada pemalsuan adalah bahwa mereka seharusnya tidak dapat diubah dalam beberapa hal, tetapi karena mereka memiliki status (yaitu mereka tahu jika mereka telah dipanggil), kekekalan itu harus dibatasi hanya pada perilaku mematikan, saya berasumsi.

@mroderick mungkin orang yang tepat untuk menjawab ini ...

Jika ini adalah perilaku yang benar, setidaknya kita harus memperbarui dokumen.

@ fatso83 Sangat dihargai! .restore doc menyebutkan palsu:

image

dari sini .

Saya sendiri tergigit oleh bug ini, jadi ini akan menyenangkan untuk diperbaiki.

Jika tidak ada orang lain yang membuat PR untuk itu dalam beberapa hari ke depan, saya dapat melihat apakah saya dapat menemukan waktu untuk memperbaikinya

Saya melihat ini sekarang dan dokumennya agak menyesatkan, seperti pengujian di atas. Ini sebenarnya tampaknya melakukan (hampir) apa yang dikatakannya, tetapi mari kita definisikan beberapa istilah terlebih dahulu:

restore - memulihkan sandbox berarti memulihkan semua fungsi yang dipotong ke keadaan semula, yang berarti stub dihapus dari setiap objek jika mereka menimpa aslinya.
reset - mengatur ulang berarti bahwa status setiap pemalsuan yang dibuat dihapus, tetapi mereka masih ada pada objek.

Masalah dengan tes di atas adalah itu

  1. Menghapus semua barang palsu dari kotak pasir
  2. Kemudian melanjutkan untuk memeriksa koleksi palsu di kotak pasir (sekarang kosong) dan mencoba untuk mengatur ulang daftar palsu (kosong)

Itu tidak masuk akal :-)

Saya telah menguji dan panggilan reset dan restore berfungsi sebagaimana mestinya. Hampir ... reset membersihkan keadaan calledOnce , tetapi lastArgument tampaknya tidak dihapus. Memeriksa lebih lanjut untuk melihat apakah saya kehilangan beberapa detail.

Menutup ini sebagai tidak dapat direkonstruksi, tetapi membuka terbitan baru pada bug fake.lastArg .

Untuk memverifikasi: https://runkit.com/fatso83/sinon-issue-2065

Saya dapat mengonfirmasi bahwa bug ini juga terjadi pada saya, saya memiliki skenario pengujian yang mengharuskan penerapannya utuh, tetapi fungsi tersebut membawa hasil rintisan dari pengujian sebelumnya, yang berarti sandbox.restore() tidak melakukan apa dimaksudkan untuk dilakukan.

Ini terjadi pada saya pada versi 7.5.0

@ oscarr-reyes Dapatkah Anda memeriksa apakah https://github.com/sinonjs/sinon/commit/54df7f7000a9db2dd05319daa49518f3cd5a5dd7 memperbaikinya untuk Anda? Saya pikir itu belum membuatnya menjadi rilis baru.

@ oscarr-reyes Apakah Anda dapat membuat contoh yang dapat direproduksi? Kami belum benar-benar melihat bug ini. Jika Anda melihat utas di atas, dan penjelasan saya, Anda akan melihat satu-satunya bug yang kami temukan adalah satu bendera belum dihapus. Segala sesuatu yang lain bekerja. Jadi kecuali kita benar-benar melihat beberapa bukti, tidak ada bug (selain dari flag lastArg).

Saya menghadapi masalah yang sama.

Saya meng-sandbox middleware "validateCaptcha" saya dan ketika saya memulihkannya, stub terus diterbitkan.

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

Apa yang saya lakukan untuk memeriksa bahwa itu tidak berhasil adalah:
1) Mengolok-olok untuk tes pertama
2) Kembalikan untuk yang berikut ini

Di dalam beforeAll ada komentar "sandbox.restore ();" yang telah saya coba dan di sana berhasil ... tetapi tidak ada gunanya

Saya juga melakukan require setiap kali ke app.js saya

Lima menit yang lalu saya telah mengubahnya menjadi:

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

Saya melihat masalah ini juga. Mengapa ini ditutup?

Mungkin perilaku pemulihan sensitif terhadap sintaks spesifik yang digunakan untuk menyiapkan rintisan. Afaik kedua _harus_ ini menjadi cara yang valid untuk melakukan ini tetapi pemulihan () berbeda. Di satu hal itu berhasil dan di sisi lain ia memiliki hasil yang tidak terduga.

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 ketika Anda melakukan tugas langsung ke db.query , maka sinon tidak memiliki cara untuk mengetahui apa yang perlu dipulihkan atau berapa nilainya sebelum tugas.

@scottpatrickwright Ditutup karena tidak ada bug, seperti yang terlihat dari utas. Itu hanya kesalahan pengguna, seperti dalam kasus Anda: ini berfungsi seperti yang dijelaskan dan dimaksudkan :-)

Sandbox Sinon dapat membersihkan hal-hal yang diketahuinya. Itu berarti Sinon harus memiliki pengetahuan tentang objek yang berinteraksi dengannya. Rintisan yang Anda jelaskan di atas dibuat mandiri. Sinon tidak mengetahui objek apa pun yang Anda tetapkan. Itu berubah pada contoh kedua. Anda juga bisa melakukan sinon.replace(obj, fieldname, fake) untuk mencapai hal yang sama. Ini hanya JavaScript 🙂

Cukup adil - terima kasih atas penjelasannya.

Pada hari Jumat, 19 Feb 2021 pukul 07.02 Carl-Erik Kopseng [email protected]
menulis:

@scottpatrickwright https://github.com/scottpatrickwright Sudah ditutup
karena tidak ada bug, seperti yang terlihat dari utas. Itu hanya
kesalahan pengguna, seperti dalam kasus Anda: ini berfungsi seperti yang dijelaskan dan dimaksudkan :-)

Sandbox Sinon dapat membersihkan hal-hal yang diketahuinya. Itu artinya Sinon punya
untuk memiliki pengetahuan tentang objek yang berinteraksi dengannya. Rintisan Anda
uraikan di atas dibuat mandiri. Sinon tidak mengetahui apa pun dari
objek yang Anda tetapkan. Itu berubah pada contoh kedua. Anda bisa
juga lakukan sinon.replace (obj, fieldname, palsu) untuk mencapai hal yang sama. Hanya saja
JavaScript 🙂

-
Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/sinonjs/sinon/issues/2065#issuecomment-782032440 , atau
berhenti berlangganan
https://github.com/notifications/unsubscribe-auth/AAKKRTFVMGEYVIB5GSIDXKTS7ZHMRANCNFSM4IGBASQQ
.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat