मैं मोचा और ची के साथ वादों का ठीक से परीक्षण कैसे करूं?


148

निम्नलिखित परीक्षा अजीब व्यवहार कर रही है:

it('Should return the exchange rates for btc_ltc', function(done) {
    var pair = 'btc_ltc';

    shapeshift.getRate(pair)
        .then(function(data){
            expect(data.pair).to.equal(pair);
            expect(data.rate).to.have.length(400);
            done();
        })
        .catch(function(err){
            //this should really be `.catch` for a failed request, but
            //instead it looks like chai is picking this up when a test fails
            done(err);
        })
});

मुझे एक अस्वीकृत वादे को कैसे ठीक से संभालना चाहिए (और इसका परीक्षण करें)?

मुझे एक असफल परीक्षा को कैसे ठीक से संभालना चाहिए (यानी expect(data.rate).to.have.length(400);:?

यहाँ कार्यान्वयन मैं परीक्षण कर रहा हूँ:

var requestp = require('request-promise');
var shapeshift = module.exports = {};
var url = 'http://shapeshift.io';

shapeshift.getRate = function(pair){
    return requestp({
        url: url + '/rate/' + pair,
        json: true
    });
};

जवाबों:


233

हाल ही के संस्करणों में मोचा के समर्थन में निर्मित वादों का उपयोग करने के लिए सबसे आसान काम होगा:

it('Should return the exchange rates for btc_ltc', function() { // no done
    var pair = 'btc_ltc';
    // note the return
    return shapeshift.getRate(pair).then(function(data){
        expect(data.pair).to.equal(pair);
        expect(data.rate).to.have.length(400);
    });// no catch, it'll figure it out since the promise is rejected
});

या आधुनिक नोड और async / प्रतीक्षा के साथ:

it('Should return the exchange rates for btc_ltc', async () => { // no done
    const pair = 'btc_ltc';
    const data = await shapeshift.getRate(pair);
    expect(data.pair).to.equal(pair);
    expect(data.rate).to.have.length(400);
});

चूंकि यह दृष्टिकोण वादों का अंत है, यह परीक्षण करना आसान है और आपको उन अजीब मामलों के बारे में सोचने की ज़रूरत नहीं होगी जिनके बारे में आप done()हर जगह अजीब कॉल की तरह सोच रहे हैं ।

यह एक लाभ है मोचा के पास इस समय जैस्मीन जैसे अन्य पुस्तकालय हैं। आप चैई अस प्रॉमिस की जाँच भी कर सकते हैं जो इसे और भी आसान बना देगा (नहीं .then) लेकिन व्यक्तिगत रूप से मैं वर्तमान संस्करण की स्पष्टता और सरलता को पसंद करता हूँ


4
मोचा के किस संस्करण में यह शुरू हुआ था? Ensure the done() callback is being called in this testमोचा 2.2.5 के साथ ऐसा करने का प्रयास करने पर मुझे एक त्रुटि मिलती है ।
स्कॉट

14
@ इसमें कोई doneपैरामीटर नहीं लिया itजाएगा जो इससे बाहर निकलेगा।
बेंजामिन ग्रुएनबाम

2
यह मेरे लिए बहुत मददगार था। doneमेरे itकॉलबैक में निकालना , और कॉलबैक में स्पष्ट रूप से कॉल करना return(वादे पर) यह है कि मुझे यह कैसे काम करना पड़ा, ठीक उसी तरह जैसे कोड स्निपेट में होता है।
जॉनीकोडर

5
बहुत बढ़िया जवाब, सही काम करता है। डॉक्स को पीछे देखते हुए, यह वहां है - मुझे लगता है कि याद करना आसान है। Alternately, instead of using the done() callback, you may return a Promise. This is useful if the APIs you are testing return promises instead of taking callbacks:
फेडरिको

4
स्कॉट जैसी ही समस्या है। मैं कॉल doneकरने के लिए एक पैरामीटर नहीं दे रहा हूं it, और यह अभी भी हो रहा है ...

43

जैसा कि पहले ही बताया जा चुका है , मोचा के नए संस्करण पहले से ही प्रॉमिस-अवेयर हैं। लेकिन जब से ओपी ने चाई के बारे में विशेष रूप से पूछा, यह केवल chai-as-promisedपैकेज को इंगित करने के लिए उचित है जो परीक्षण वादों के लिए एक स्वच्छ वाक्यविन्यास प्रदान करता है:

का उपयोग कर के रूप में वादा किया

यहां बताया गया है कि आप एक वादे के लिए दोनों resolveऔर rejectमामलों का परीक्षण करने के लिए ची- ए -वादा का उपयोग कैसे कर सकते हैं :

var chai = require('chai');
var expect = chai.expect;
var chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised);

...

it('resolves as promised', function() {
    return expect(Promise.resolve('woof')).to.eventually.equal('woof');
});

it('rejects as promised', function() {
    return expect(Promise.reject('caw')).to.be.rejectedWith('caw');
});

बिना ची-के-जैसा वादा किया

इसे वास्तव में स्पष्ट करने के लिए कि क्या परीक्षण किया जा रहा है, यहाँ एक ही उदाहरण को बिना ची-के-वादे के रूप में कोडित किया गया है:

it('resolves as promised', function() {
    return Promise.resolve("woof")
        .then(function(m) { expect(m).to.equal('woof'); })
        .catch(function(m) { throw new Error('was not supposed to fail'); })
            ;
});

it('rejects as promised', function() {
    return Promise.reject("caw")
        .then(function(m) { throw new Error('was not supposed to succeed'); })
        .catch(function(m) { expect(m).to.equal('caw'); })
            ;
});

5
दूसरे दृष्टिकोण के साथ समस्या यह है कि असफल catchहोने पर लागू किया जाता है expect(s)। यह एक गलत धारणा देता है कि वादा विफल हो गया, भले ही वह ऐसा नहीं हुआ। यह केवल उम्मीद है कि असफल रहा।
theCrazyProgrammer

2
मुझे बताने के लिए पवित्र हेक धन्यवाद मुझे Chai.useइसे माउंट करने के लिए कॉल करना होगा। मैंने कभी नहीं लिया है कि वे प्रलेखन से था। |:
आर्किम

3

यहाँ मेरा ले रहा है:

  • का उपयोग करते हुए async/await
  • अतिरिक्त ची मॉड्यूल की जरूरत नहीं है
  • कैच इश्यू से बचने के लिए, @TheCrazyProgrammer ने ऊपर बताया

विलंबित वादा फ़ंक्शन, जो विफल हो जाता है, अगर 0 की देरी दी जाए:

const timeoutPromise = (time) => {
    return new Promise((resolve, reject) => {
        if (time === 0)
            reject({ 'message': 'invalid time 0' })
        setTimeout(() => resolve('done', time))
    })
}

//                     ↓ ↓ ↓
it('promise selftest', async () => {

    // positive test
    let r = await timeoutPromise(500)
    assert.equal(r, 'done')

    // negative test
    try {
        await timeoutPromise(0)
        // a failing assert here is a bad idea, since it would lead into the catch clause…
    } catch (err) {
        // optional, check for specific error (or error.type, error. message to contain …)
        assert.deepEqual(err, { 'message': 'invalid time 0' })
        return  // this is important
    }
    assert.isOk(false, 'timeOut must throw')
    log('last')
})

सकारात्मक परीक्षण बल्कि सरल है। अनपेक्षित असफलता (अनुकरण करके 500→0) परीक्षण स्वचालित रूप से विफल हो जाएगा, क्योंकि अस्वीकृत वादा आगे बढ़ता है।

नेगेटिव टेस्ट , कोशिश-कैच-विचार का उपयोग करता है। हालाँकि: एक अवांछित पास के बारे में 'शिकायत' कैच क्लॉज के बाद ही होती है (इस तरह, यह कैच में समाप्त नहीं होता है) क्लॉज़, आगे और भ्रामक त्रुटियों को ट्रिगर करता है।

काम करने की इस रणनीति के लिए, किसी को कैच क्लॉज से टेस्ट वापस करना होगा। यदि आप किसी और चीज़ का परीक्षण नहीं करना चाहते हैं, तो इसे दूसरे () - ब्लॉक का उपयोग करें।


2

थ्रे एक बेहतर उपाय है। कैच ब्लॉक में किए गए त्रुटि को वापस करें।

// ...

it('fail', (done) => {
  // any async call that will return a Promise 
  ajaxJson({})
  .then((req) => {
    expect(1).to.equal(11); //this will throw a error
    done(); //this will resove the test if there is no error
  }).catch((e) => {
    done(e); //this will catch the thrown error
  }); 
});

यह परीक्षण निम्नलिखित संदेश के साथ विफल हो जाएगा: AssertionError: expected 1 to equal 11

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.