<p>sinon.restore () &amp;&amp; sandbox.restore () وليس استعادة المنتجات المقلدة</p>

تم إنشاؤها على ٢٣ يوليو ٢٠١٩  ·  16تعليقات  ·  مصدر: sinonjs/sinon

صف الخلل
لا يمكن مسح المنتجات المقلدة sinon.restore() (ولا resetHistory ، resetBehavior ، ولا reset ). ثم حاولت إنشاء صندوق رمل جديد ، ومسح آلية الرمل. لا نرد. هل هذا مقصود؟

لإعادة إنتاج

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

سلوك متوقع
توقعت أن يكون thing.lastArg إما undefined أو null . يعطيني "Hi"

لقطات
غير متاح

السياق (يرجى استكمال المعلومات التالية):

  • إصدار المكتبة: Sinon ^ 7.3.2
  • البيئة: العقدة 10.16.0
  • مثال URL: N / a
  • المكتبات الأخرى التي تستخدمها: Mocha، Chai

سياق إضافي
مجرد اختبار قدرات Sinon حيث أستخدمها لاختبار الخلفية.

Bug Help wanted

التعليق الأكثر فائدة

عادل بما فيه الكفاية - شكرا للتوضيح.

يوم الجمعة 19 فبراير 2021 الساعة 7:02 صباحًا Carl-Erik Kopseng [email protected]
كتب:

scottpatrickwright https://github.com/scottpatrickwright انها مغلقة
لأنه لا يوجد خلل كما يجب أن يتضح من الخيط. كان ذلك عادلاً
خطأ المستخدم ، كما في حالتك: يعمل بالشكل الموصوف والمقصود :-)

يمكن لـ Sinon sandbox تنظيف الأشياء التي يعرف عنها. هذا يعني أن سينون لديه
لمعرفة الأشياء التي يتفاعل معها. كعب أنت
وصف أعلاه بذاته. لم يتم علم Sinon بأي من
الكائنات التي تقوم بتعيينها لها. يتغير ذلك في المثال الثاني. يمكنك
قم أيضًا باستبدال sinon. (obj ، اسم المجال ، وهمي) لتحقيق نفس الشيء. انه فقط
جافا سكريبت 🙂

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/sinonjs/sinon/issues/2065#issuecomment-782032440 ، أو
إلغاء الاشتراك
https://github.com/notifications/unsubscribe-auth/AAKKRTFVMGEYVIB5GSIDXKTS7ZHMRANCNFSM4IGBASQQ
.

ال 16 كومينتر

كما هو ، يبدو وكأنه خطأ ، ولكن لأكون صادقًا ، لست متأكدًا تمامًا من هذا الأمر. أتذكر نقطة أساسية في المنتجات المقلدة وهي أنه كان من المفترض أن تكون غير قابلة للتغيير إلى حد ما ، ولكن نظرًا لأن لديهم حالة (أي يعرفون ما إذا كان قد تم استدعاؤهم) ، يجب أن يقتصر هذا الثبات على سلوك stubbing فقط ، على ما أفترض.

mroderick قد يكون الشخص المناسب للإجابة على هذا ...

إذا كان هذا هو السلوك الصحيح ، فيجب علينا على الأقل تحديث المستندات.

@ fatso83 في غاية الامتنان! المستند .restore المذكور مزيف:

image

من هنا .

لقد كان هذا الخطأ نفسي قليلاً ، لذلك سيكون من الجيد إصلاحه.

إذا لم يقم أي شخص آخر بعمل علاقات عامة له في الأيام القليلة المقبلة ، يمكنني معرفة ما إذا كان بإمكاني العثور على الوقت لإصلاحه

لقد نظرت في هذا الآن والمستندات مضللة بعض الشيء ، كما هو الحال في الاختبار أعلاه. يبدو في الواقع أنه يفعل (تقريبًا) ما يقوله ، لكن دعنا نحدد بعض المصطلحات أولاً:

الاستعادة - تعني استعادة وضع الحماية استعادة جميع الوظائف المتوقفة إلى حالتها الأصلية ، مما يعني إزالة الأجزاء الجذرية من كل كائن في حالة الكتابة فوق الأصل.
إعادة التعيين - إعادة الضبط تعني مسح حالة كل من المنتجات المزيفة التي تم إنشاؤها ، لكنها لا تزال موجودة على الكائنات.

المشكلة في الاختبار أعلاه هي أنه

  1. يزيل جميع المنتجات المقلدة من الصندوق الرمل
  2. ثم ينتقل إلى مجموعة المنتجات المقلدة في صندوق الحماية (فارغ الآن) ويحاول إعادة تعيين قائمة المنتجات المقلدة (الفارغة)

هذا غير منطقي :-)

لقد اختبرت وعملت مكالمات reset و restore كما ينبغي. تقريبًا ... ينظف reset حالة calledOnce ، لكن يبدو أن lastArgument لم يتم مسحه. تحقق أكثر قليلاً لمعرفة ما إذا كنت قد فقدت بعض التفاصيل.

إغلاق هذا على أنه غير قابل للتكرار ، ولكن مع فتح إصدار جديد في الخطأ fake.lastArg .

للتحقق: https://runkit.com/fatso83/sinon-issue-2065

أستطيع أن أؤكد أن هذا الخطأ يحدث لي أيضًا ، ولدي سيناريو اختبار يتطلب أن يكون التنفيذ سليمًا ، لكن الوظيفة تحمل نتيجة كعب الروتين من اختبار سابق ، مما يعني أن sandbox.restore() لا يفعل ما يعتزم القيام به.

هذا يحدث لي في الإصدار 7.5.0

@ oscarr-reyes هل يمكنك التحقق مما إذا كان https://github.com/sinonjs/sinon/commit/54df7f7000a9db2dd05319daa49518f3cd5a5dd7 يصلح لك؟ أعتقد أنه لم يتم تحويله إلى إصدار جديد بعد.

@ oscarr-reyes هل أنت قادر على تقديم مثال قابل للتكرار؟ لم نر هذا الخطأ بعد في الواقع. إذا نظرت إلى الخيط أعلاه ، وشرح لي ، سترى الخطأ الوحيد الذي وجدنا أنه لم يتم مسح علامة واحدة. كل شيء آخر يعمل. لذلك ما لم نرى بعض الأدلة بالفعل ، فلا يوجد خطأ (باستثناء علامة LastArg).

لقد واجهت نفس المشكلة.

أنا بصدد وضع الحماية لبرنامج "validateCaptcha" الوسيط الخاص بي وعندما أستعيده يستمر في إصدار كعب روتين.

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

ما أفعله للتحقق من عدم نجاحه هو:
1) اسخر منه للاختبار الأول
2) قم باستعادته لما يلي

بالداخل beforeAll هناك تعليق "sandbox.restore ()؛" لقد حاولت وهناك نجحت ... لكنها عديمة الفائدة

أنا أحتاج أيضًا في كل مرة إلى app.js

قبل خمس دقائق ، قمت بتعديله إلى:

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

أنا أرى هذه القضية أيضًا. لماذا هذا مغلق؟

قد يكون سلوك الاستعادة حساسًا للصيغة المحددة المستخدمة لإعداد كعب الروتين. يجب أن تكون كلتا هاتين الطريقتين _should_ صالحة للقيام بذلك ولكن الاستعادة () مختلفة. في أحدهما يعمل والآخر له نتائج غير متوقعة.

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 عندما تقوم بمهام مباشرة إلى db.query ، فلن يكون لدى sinon طريقة لمعرفة ما يجب استعادته أو القيمة التي كانت قبل المهمة.

scottpatrickwright إنه مغلق لأنه لا يوجد خطأ ، كما يجب أن يتضح من الموضوع. لقد كان مجرد خطأ من المستخدم ، كما في حالتك: يعمل كما هو موضح والمقصود :-)

يمكن لـ Sinon sandbox تنظيف الأشياء التي يعرف عنها. هذا يعني أن Sinon يجب أن يكون لديه معرفة بالأشياء التي يتفاعل معها. كعب الروتين الذي وصفته أعلاه مصنوع بشكل مستقل. لم يتم علم Sinon بأي من الكائنات التي تقوم بتعيينها لها. يتغير ذلك في المثال الثاني. يمكنك أيضًا عمل sinon.replace(obj, fieldname, fake) لتحقيق نفس الشيء. إنها مجرد JavaScript 🙂

عادل بما فيه الكفاية - شكرا للتوضيح.

يوم الجمعة 19 فبراير 2021 الساعة 7:02 صباحًا Carl-Erik Kopseng [email protected]
كتب:

scottpatrickwright https://github.com/scottpatrickwright انها مغلقة
لأنه لا يوجد خلل كما يجب أن يتضح من الخيط. كان ذلك عادلاً
خطأ المستخدم ، كما في حالتك: يعمل بالشكل الموصوف والمقصود :-)

يمكن لـ Sinon sandbox تنظيف الأشياء التي يعرف عنها. هذا يعني أن سينون لديه
لمعرفة الأشياء التي يتفاعل معها. كعب أنت
وصف أعلاه بذاته. لم يتم علم Sinon بأي من
الكائنات التي تقوم بتعيينها لها. يتغير ذلك في المثال الثاني. يمكنك
قم أيضًا باستبدال sinon. (obj ، اسم المجال ، وهمي) لتحقيق نفس الشيء. انه فقط
جافا سكريبت 🙂

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/sinonjs/sinon/issues/2065#issuecomment-782032440 ، أو
إلغاء الاشتراك
https://github.com/notifications/unsubscribe-auth/AAKKRTFVMGEYVIB5GSIDXKTS7ZHMRANCNFSM4IGBASQQ
.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات