هذا الاختبار:
it('returns the correct value', function(done) {
var returnValue = 5;
aPromise.then(function() {
expect(returnValue).to.equal(42);
done();
});
});
فشل هذا الاختبار مع timeout of 2000ms exceeded
بدلاً من خطأ التأكيد. أعتقد أن هذا يرجع إلى أن المكالمة expect()
تسبب في حدوث خطأ ، ولم يتم تنفيذ done()
أبدًا ، وأنا أتساءل عما إذا كانت هناك طريقة أفضل لاختبار هذا النوع من الكود.
هل تم حل aPromise
الإطلاق؟ إذا لم يكن الأمر كذلك ، فلن يكون هناك خيار كبير سوى التخلي عن مهلة.
NickHeiner نعم ، تقرر ؛ ثم يجد expect()
أن returnValue
ليس equal(42)
ويلقي.
gurdiga كيف تعرف أنه يرمي إذا حصلت على مهلة وليس خطأ تأكيد؟
hallasNickHeiner هنا هو الشيء تشغيل: http://jsfiddle.net/gurdiga/p9vmj/.
gurdiga يبدو لي أن خطأه الخاص. حاول إضافة .catch(done)
إلى وعدك وأعتقد أنه سيعمل على النحو المنشود.
hallas نجاح باهر: _that_ كان الجواب! :) يبدو أن aPromise.finally()
هو الخيار الأمثل لوضع done
فيه: يجب أيضًا استدعاؤه عند الوفاء بالوعد. ؛)
شكرا لك!
أشعر بالغباء.
أعتقد أنني حصلت عليه أخيرًا: عندما يتم طرح أي شيء في أي من وظائف معالج الوعد ، سواء كان ذلك الذي تم تمريره إلى .then()
، إلى .catch()
أو إلى .finally()
، يكون الخطأ هو تم التعامل معها من خلال مكتبة الوعد. بهذه الطريقة ، لا يرى عداء الاختبار الخطأ الحقيقي أبدًا ، ولا يتم استدعاء done()
أبدًا (لأن شيئًا قبل طرح خطأ تأكيد) ، وبالتالي فإن خطأ المهلة هو كل ما تحصل عليه من عداء الاختبار.
للتخلص من الوعد ، أستخدم setTimeout()
:
it('returns the correct value', function(done) {
var returnValue = 5;
aPromise.then(function() {
setTimeout(function() {
expect(returnValue).to.equal(42);
done();
});
});
});
لقد وجدت أن هذه هي الطريقة الوحيدة للحصول على رسائل خطأ مناسبة وسلوك عداء الاختبار.
مع تمرير done
إلى .catch()
أو .finally()
يعتبر الاختبار ناجحًا في أي حال ، لذلك إذا كانت هناك أخطاء في التأكيد ، فلن تراها أبدًا.
واجهت مشكلة مماثلة ، وأدركت في النهاية أنه لا يجب عليك استخدام المنفذ عند اختبار الوظائف غير المتزامنة مع الوعود ، بدلاً من ذلك ، فقط أعد الوعد. لذلك يجب أن تكون قادرًا على القيام بذلك دون انقضاء المهلة ، على سبيل المثال:
it('returns the correct value', function() {
var returnValue = 5;
return aPromise.then(function() {
expect(returnValue).to.equal(42);
});
});
أعتقد أن هذه القضية لا تزال قائمة. لدي مشكلة انتهاء مهلة لا يمكن حلها من خلال إعادة وعد لأن الوحدة الخاصة بي لا تستخدم الوعود.
it("works", function(done) {
new Something()
.on("eventA", function(result) {
expect(result).to.be.true;
})
.on("eventB", function(result) {
expect(result).to.be.false;
done();
});
});
Promise
مبالغ فيه.try
/ catch
يبدو أيضًا مفرطًا ، والأهم من ذلك أنه ينتج عنه Error: done() called multiple times
.الأفكار:
http://staxmanade.com/2015/11/testing-asyncronous-code-with-mochajs-and-es7-async-await/
فيما يتعلق بتوصيات منشور المدونة ، لا أعرف شيئًا عن معالجة أخطاء الوظيفة غير المتزامنة ، ولكن بالنسبة للوعود الواضحة ، فإن توصية try-catch غريبة: محاولة الوعد الأصلية بدون محاولة التقاط كانت صحيحة تقريبًا ، فقد احتاجت فقط إلى استخدام .catch(done)
بدلاً من استخدام المعلمة الثانية لـ then
كـ done
. (صحيح ، نظرًا لأن Mocha لديها دعم مباشر للوعود ، يمكنك أيضًا إرجاع الوعد ، ولكن لما يستحق ...) لم تكن المشكلة في مثال الوعد الأولي عدم وجود try-catch ، بل كان ذلك المعالج الثاني إلى then
لا يُستدعى مع استثناءات طرحها المعالج الأول ، بينما التالي catch
هو ؛ لا أعرف ما هو الأساس المنطقي لتصميم الوعود بهذه الطريقة ، لكن هذا هو مدى الوعود. بالإضافة إلى ذلك ، إذا كان هناك العديد من then
s لسبب ما ، فستكون هناك حاجة إلى .catch(done)
نهائي واحد فقط ، وهي نقطة تفوق على المحاولة داخل المعالجات (فوق حقيقة أن .catch(done)
أقل معيارية لتبدأ).
بالنسبة لواجهة برمجة التطبيقات الخاصة بك:
.on("error", function(error) {...})
) ، فلن يصلوا إلى Mocha أبدًا ما لم تستمع إليهم ولديك يستدعي المستمع done
مع الخطأ (أو استخدم فقط done
مع المستمع إذا مر المستمع بالخطأ كمعامله الأول ، على سبيل المثال .on("error", done)
. من المفترض أن هذا سيفترض أيضًا فقط يجب كتابتها مرة واحدة لكل اختبار ، بدلاً من مرة واحدة لكل معالج حدث ، مثل .catch(done)
في الوعد."end"
/ "drain"
للتحقق مما إذا تم تعيين القيم المنطقية في الأحداث الأخرى.عذرًا ، ما زلت لا أعرف كيف يُفترض أن تبلغ واجهة برمجة التطبيقات API عن الأخطاء.
نعم ، لقد كنت أعتمد حتى الآن على المهلات الزمنية لـ _عندما تفشل بعض الأشياء ، ثم أحفر يدويًا لاكتشاف _كيف / لماذا _. لحسن الحظ ، نادراً ما تنكسر الأشياء ، لكن هذا ليس عذراً لعدم وجود تصميم أفضل (من جانبي ، في الغالب).
stevenvachon : سامحني مقدمًا ، لكنني لا أرى مشكلة فورية في uncaughtException
(ما لم يكن تنفيذ باعث الحدث يصطاد أخطاء المستمع ويصدر حدث error
أو شيء ما ، والذي لا يزال من السهل بعد ذلك يحل).
الآن ، إذا كان تنفيذك تحت غطاء المحرك يستخدم الوعود ، لكنه يرسل الأحداث بدلاً من فضح الوعد ، فإن تأكيداتك ستُؤكل بالفعل. الطريقة التي يمكنني بها التغلب على هذه المشكلة هي استخدام unhandledRejection
.
عادةً ما أضع هذا في برنامج نصي للإعداد يتم تشغيله قبل اختباراتي:
process.on('unhandledRejection', function (reason)
{
throw reason;
});
ملاحظة: قد يحتاج هذا إلى بعض الشحوم الإضافية للعمل في المتصفحات.
آمل أن أرى Mocha يدعم هذا كما يفعل uncaughtException
لأن هذه حالة استخدام شائعة ؛ لمجرد أنني أستخدم الوعود لا يعني أنني أريد إعادتها إلى المتصل!
تواجه نفس المشكلة مع
it('Convert files into base64', (resolve) => {
let files = Promise.all(promises);
return files
.then(([actual, expected]) => {
assert.equal(actual, expected, 'Files not are equal');
resolve();
})
.catch(error => resolve);
});
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.
.catch
خطأ. error => resolve
يعادل function(error) { return resolve }
، مما يعني أنه لن يتم استدعاء resolve
وسيتم تجاهل الخطأ. ما تريده هو استدعاء resolve
مع ظهور الخطأ ، والذي سيكون error => resolve(error)
. بالطبع ، تمرير دالة رد الاتصال X
التي تستدعي ببساطة الوظيفة Y
بنفس الوسيطات التي يُطلق عليها X
تعادل مجرد تمرير Y
مثل رد الاتصال ، لذلك حتى .catch(error => resolve(error))
يمكن تبسيطها إلى .catch(resolve)
. (ستحتاج فقط إلى عدم تمرير resolve
مباشرةً إذا كنت تمرره إلى then
، وبالتالي ، هناك حاجة لتجنب تمرير معامل النتيجة then
إلى resolve
لمنع معاملته كخطأ: then(()=>resolve())
بدلاً من .then(resolve)
؛ ولكن نظرًا لأنك تستخدم رد الاتصال then
للتأكيدات ، فإن هذا لا يحدث .)
(أيضًا ، بشكل اصطلاحي ، من المحتمل أن يتم تسمية resolve
هنا بشيء على غرار done
، لأنه يتعامل مع كل من النجاح والفشل والقضاة الذي يعتمد على ما إذا كان قد تم استدعاؤه بحجة أو لا. ومن هنا الاسم الوارد في رسالة الخطأ الخاصة بـ Mocha. ولكن قد تكون هذه نقطة خلافية ؛ واصل القراءة.)
ومع ذلك ، في هذه الحالة ، يمكنك تبسيطها أكثر من خلال إعادة الوعد فقط وعدم استخدام معلمة الاختبار التي تم إجراؤها على الإطلاق ، حيث ستنتظر Mocha الوعد بالنجاح أو الفشل كإشارة إلى نجاح الاختبار أو فشله (بشرط عدم وجود معلمة تم إجراؤها وظيفة الاختبار ؛ السلوك في حالة استخدام كليهما لا يزال قيد التجزئة):
it('Convert files into base64', () => {
let files = Promise.all(promises);
return files
.then(([actual, expected]) => {
assert.equal(actual, expected, 'Files not are equal');
})
});
lsphillips التي تناسبني. شكرا!! آمل أن أرى المخاوي يدعم هذا بشكل افتراضي أيضًا. لقد خلقت للتو # 2640.
استغرقت مني بعض الوقت لأعمل على ذلك! بناءً على الإجابات أعلاه ، هذان هما الخياران:
npm install --save mocha expect.js q
./node_modules/mocha/bin/mocha test.spec.js
// test.spec.js
var $q = require('q');
var expect = require('expect.js');
describe('tests with done', function(){
it('returns the correct value from promise', function(done) {
var returnValue = 5;
var def = $q.defer();
def.promise.then((val) => {
expect(val).to.equal(42);
done();
}).catch(done);
def.resolve(returnValue)
});
})
describe('tests returning promises', function(){
it('returns the correct value from promise', function() {
var returnValue = 5;
var def = $q.defer();
def.resolve(returnValue)
return def.promise.then((val) => {
expect(val).to.equal(42);
});
});
})
tests with done
1) returns the correct value from promise
tests returning promises
2) returns the correct value from promise
0 passing (15ms)
2 failing
1) tests with done returns the correct value from promise:
Error: expected 5 to equal 42
at Assertion.assert (node_modules/expect.js/index.js:96:13)
at Assertion.be.Assertion.equal (node_modules/expect.js/index.js:216:10)
at def.promise.then (tests/test.spec.js:9:24)
at _fulfilled (node_modules/q/q.js:854:54)
at self.promiseDispatch.done (node_modules/q/q.js:883:30)
at Promise.promise.promiseDispatch (node_modules/q/q.js:816:13)
at node_modules/q/q.js:570:49
at runSingle (node_modules/q/q.js:137:13)
at flush (node_modules/q/q.js:125:13)
at _combinedTickCallback (internal/process/next_tick.js:67:7)
at process._tickCallback (internal/process/next_tick.js:98:9)
2) tests returning promises returns the correct value from promise:
Error: expected 5 to equal 42
at Assertion.assert (node_modules/expect.js/index.js:96:13)
at Assertion.be.Assertion.equal (node_modules/expect.js/index.js:216:10)
at def.promise.then (tests/test.spec.js:22:24)
at _fulfilled (node_modules/q/q.js:854:54)
at self.promiseDispatch.done (node_modules/q/q.js:883:30)
at Promise.promise.promiseDispatch (node_modules/q/q.js:816:13)
at node_modules/q/q.js:570:49
at runSingle (node_modules/q/q.js:137:13)
at flush (node_modules/q/q.js:125:13)
at _combinedTickCallback (internal/process/next_tick.js:67:7)
at process._tickCallback (internal/process/next_tick.js:98:9)
gurdiga شكرا
في السيناريو الخاص بي ، استخدمت Nightmare لإنهاء الاختبارات. كان الحل بالنسبة لي هو استخدام .catch(done)
. يمكنك الاتصال بـ done(error)
داخل رد اتصال آخر كما في المثال أدناه.
describe('Clicking in any bad reputation tag', () => {
it('open the bad reputation modal', (done) => {
nightmare
.select('#per-page', '50')
.waitForAjax()
.click('[data-reputation="bad"]')
.evaluate(function() {
return document.querySelector('.vue-modal .ls-modal-title').innerText
})
.then(function(title) {
title.should.equal('Sua segmentação teve uma avaliação ruim!')
done()
})
.catch((error) => {
screenshot(nightmare)
done(error)
})
})
})
itumoraes يعمل ، ولكن يمكنك القيام بذلك بدلاً من ذلك:
describe('Clicking in any bad reputation tag', () => {
it('open the bad reputation modal', () => {
return nightmare
.select('#per-page', '50')
.waitForAjax()
.click('[data-reputation="bad"]')
.evaluate(function() {
return document.querySelector('.vue-modal .ls-modal-title').innerText
})
.then(function(title) {
title.should.equal('Sua segmentação teve uma avaliação ruim!')
})
})
})
لا تحتاج إلى الاتصال بـ done()
إذا عدت بوعد. شاهد منشور مدونتي
لقد استخدمت البرنامج النصي أدناه ولكني حصلت على نفس خطأ تجاوز المهلة.
مخطوطة:
وصف ("getBillingDetail"، دالة غير متزامنة () {
this.timeout (55000) ؛
it.only ("تحقق من إعطاء اسم عمل صالح" ، وظيفة غير متزامنة (تم) {
this.timeout (55000) ؛
var نتيجة = await url.getBillingDetail ('12254785565647858') ؛
console.log (نتيجة) ؛
assert.equal (نتيجة ، صواب) ؛
}) ؛
}) ؛
خطأ: تجاوز المهلة 55000 مللي ثانية. بالنسبة للاختبارات غير المتزامنة والخطافات ، تأكد من استدعاء "تم ()" ؛ في حالة إعادة الوعد ، تأكد من أنه يقرر.
توقف عن تهجئة نفس الشيء في العديد من القضايا المغلقة. لا تمرر رد اتصال تم إلى وظائف غير متزامنة. اقرأ الوثائق الخاصة باختبارات عدم التزامن
Munter قمت بإزالة رد الاتصال الذي تم القيام به ، ولكن حدث هذا الخطأ مرة أخرى
يبدو أن وعدك لم يتم إعادة صياغته أبدًا.
التعليق الأكثر فائدة
واجهت مشكلة مماثلة ، وأدركت في النهاية أنه لا يجب عليك استخدام المنفذ عند اختبار الوظائف غير المتزامنة مع الوعود ، بدلاً من ذلك ، فقط أعد الوعد. لذلك يجب أن تكون قادرًا على القيام بذلك دون انقضاء المهلة ، على سبيل المثال: