Sinon: هل من الممكن إيقاف وظيفة أداة مساعدة قائمة بذاتها؟

تم إنشاؤها على ١٢ سبتمبر ٢٠١٤  ·  18تعليقات  ·  مصدر: sinonjs/sinon

العديد من الوحدات النمطية للعقدة تقوم بتصدير وظيفة واحدة (ليست وظيفة منشئ ، ولكن وظيفة "فائدة" للأغراض العامة) باعتبارها "module.exports" لها. هل من الممكن استخدام Sinon.js لإيقاف هذه الوظيفة المستقلة؟

// some module, "sum.js" that's "required" throughout the application
module.exports = function(a, b) {
    return a + b;
};

// test.js
var sum = require('sum');
...

beforeEach(function() {
    sumStub = sinon.stub(sum);
    // throws: TypeError: Attempted to wrap undefined property undefined as function
});

afterEach(function() {
   sumStub.restore();
});
...

هل هناك أي طريقة لتحقيق ذلك؟

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

جرب هذا

import * as sum from './sum'
sinon.stub(sum, 'default', () => {
  // stubbed function
});

ال 18 كومينتر

للأسف لا.

بالنسبة إلى npm ، يمكنك استخدام https://github.com/thlorenz/proxyquire أو ما شابه. كان مايكل فيذرز يسمي هذا التماس الارتباط .

إنها ليست أنيقة ، لكنها قابلة للتنفيذ.

بمجرد الانتهاء من ذلك ، يمكنك استخدام Sinon كما تفعل عادةً.

على المدى الطويل ، قد ترغب في نقل الهندسة المعمارية الخاصة بك نحو طبقات الكائن ، ولكنه حل يعمل اليوم. توجد مشاريع مماثلة لـ RequireJS.

function MyFunction(){}
module.exports = function(){ return module.exports.MyFunction.apply(this, arguments) }
module.exports.MyFunction = MyFunction

بعد ذلك يمكنك أن تطلب ('./ MyFunction'). سترى وظيفة MyFunction وبقية التعليمات البرمجية الخاصة بك دون تغيير الإصدار stubbed.

: دوار:: dizzy_face:: دوار:

عثرت على نفس الشيء في اليوم الآخر ، وهذا ما فعلته:

const proxyquire = require('proxyquire')
const sinon = require('sinon')
const sum = sinon.stub()

const ModuleWithDependency = proxyquire('module', {
  'sum': sum
})

يعمل بشكل جيد لحالتنا.

في حالة استخدام CommonJS:

const myStubbedModule = function( absoluteModulePath ) {
  const stub = sinon.stub();
  require.cache[ require.resolve( absoluteModulePath ) ] = stub;
  return stub;
}

_Note_: اعتمادًا على ما إذا كنت تقوم بالترجمة الشفوية ، قد تحتاج إلى القيام بما يلي:

require.cache[ require.resolve( absoluteModulePath ) ] = {
  default: stub,
  exports: stub
}

غالبًا أثناء الاختبارات ، سأحتاج إلى إدخال كعب واحد لاختبار واحد محدد. يتيح لي نهج وظيفة الغلاف الذي اتبعته تعديل قاعدة الشفرة وإدخال نصفي كلما أردت ، دون الاضطرار إلى اتباع نهج stub-first أو لعب whack-a-mole مع الوحدات التي تحتوي على مراجع للوحدات النمطية الأخرى التي أحاول القيام بها كعب واستبدال في المكان.

لقد تلقيت عددًا من مراجعات الكود حيث دفعني الناس نحو القرصنة في طبقة الوحدة النمطية Node ، عبر proxyquire ، mock- required ، & c ، ويبدأ الأمر بسيطًا ويبدو أقل خطورة ، ولكنه يصبح تحديًا صعبًا للغاية للحصول على بذرة يلزم وضعها في مكانها أثناء إعداد الاختبار. باستخدام proxyquire ، يمكن للمرء على الأقل طلب وكيل () إصدار صغير / حجم ثابت من التطبيق ، وشيء من المستوى الأعلى ، وسيتم إحضار جميع التنسيقات أثناء تحميلها ، ولكن معالجة هذا على مستوى لغة JS بدلاً من مستوى الوحدة النمطية Node يستمر أن تجعلني أكثر وضوحًا بشكل ملحوظ ، وأسهل في إدارتها باستمرار وبدون خطر (تحذير: طالما يتذكر المرء الاستعادة).

لقد صنعت هذه الوحدة لإخراج الوحدات النمطية بسهولة أكبر https://github.com/caiogondim/stubbable-decorator.js

كنت ألعب مع Sinon للتو ووجدت حلاً بسيطًا يبدو أنه يعمل - فقط أضف "الحجج" كحجة ثانية

const sumStub = sinon.stub(sum, 'arguments');
sumStub.withArgs(2, 2).returns(4);
sumStub.withArgs(3, 3).returns(6);

جرب هذا

import * as sum from './sum'
sinon.stub(sum, 'default', () => {
  // stubbed function
});

@ harryi3t - شكرا الذي

@ harryi3t لم ينجح ذلك بالنسبة لي ، باستخدام وحدات ES.
الخطأ: can't redefine non-configurable property "default"

وحدات elliottregan ES ليست قابلة للإلغاء وفقًا للمعيار. لدينا حتى اختبارات تغطي هذا السلوك. لا يزال بإمكانك القيام بذلك ، رغم ذلك ، كما أناقش هنا .

كثير من الناس لا يختبرون في الواقع وحدات ES ، لكنهم يقومون بترجمة وحدات ES (باستخدام Webpack / Babel ، إلخ). يستخدم ES5 الناتج محولات لمحاكاة كيفية عمل وحدات ES. ربما تفعل ذلك ، لكن جرب المسار البسيط الذي أقترحه في الموضوع المرتبط. mocha --register ... يقطع شوطًا طويلاً.

الحل الممكن

(function (defineProperty) {
    Object.defineProperty = (obj, prop, desc) => {
        desc.configurable = true;
        return defineProperty(obj, prop, desc);
    };
})(Object.defineProperty);

@ الحل البديل وحدات ES . أعتقد أن الأمر يتعلق بالتعليمات البرمجية التي تمت معالجتها بواسطة Webpack 4 ، حيث قد تنطبق (اعتمادًا على سلسلة الأدوات الخاصة بك) على التعليمات البرمجية المكتوبة باستخدام ES2015 + بناء الجملة الذي تم _ترجمته_ إلى ES5 ، _ محاكاة_ ثبات وحدات ES من خلال واصفات الكائنات غير القابلة للتكوين .

جرب هذا

import * as sum from './sum'
sinon.stub(sum, 'default', () => {
  // stubbed function
});

مهملة الآن.

لقد قمت للتو بإعادة كتابة وحدة ES6 الخاصة بي من هذا:

export default const doCoolStuff = () => {
  // do the cool stuff...
}

الى هذا:

export default {
  doCoolStuff: () => {
    // do the cool stuff...
  }
} 

إنه صعب بعض الشيء ، لكنه مكنني من لف الوظيفة في كعب.

الآن تقريبا 2021 ، هل هذا ممكن؟

الآن تقريبا 2021 ، هل هذا ممكن؟

لا يختلف كثيرًا عن 2019.
لم تتغير وحدات ES ، ولم يتغير CommonJS ، ولم تتغير JavaScript.

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