2012-06-27 14 views
73

मैं मोचा में कुछ अतुल्यकालिक परीक्षण चल रहा हूँ ब्राउज़र धावक का उपयोग कर और मैं चाय की उम्मीद शैली दावे उपयोग करने के लिए कोशिश कर रहा हूँ:चाई को एसिंक्रोनस मोचा परीक्षणों के साथ काम करने का कोई तरीका है?

window.expect = chai.expect; 
describe('my test', function() { 
    it('should do something', function (done) { 
    setTimeout(function() { 
     expect(true).to.equal(false); 
    }, 100); 
    } 
} 

यह मैं सामान्य में विफल रहा है अभिकथन संदेश नहीं देता है, बजाय मैं मिलता है:

Error: the string "Uncaught AssertionError: expected true to equal false" was thrown, throw an Error :) 
    at Runner.fail (http://localhost:8000/tests/integration/mocha/vendor/mocha.js:3475:11) 
    at Runner.uncaught (http://localhost:8000/tests/integration/mocha/vendor/mocha.js:3748:8) 
    at uncaught (http://localhost:8000/tests/integration/mocha/vendor/mocha.js:3778:10) 

तो यह स्पष्ट रूप से त्रुटि को पकड़ रहा है, यह सिर्फ इसे सही तरीके से प्रदर्शित नहीं कर रहा है। कोई जानकारी यह कैसे करनी है? मुझे लगता है कि मैं सिर्फ एक त्रुटि ऑब्जेक्ट के साथ "किया" कह सकता हूं लेकिन फिर मैं चाई की तरह कुछ लालित्य खो देता हूं और यह बहुत गुस्सा हो जाता है ...

+0

समस्या ब्राउज़र साइड मोचा के साथ है। इसके बारे में जानकारी के लिए https://github.com/visionmedia/mocha/pull/278 देखें। –

उत्तर

88

आपका अतुल्यकालिक परीक्षण एक अपवाद है, में विफल रहा है expect() ations पर, कि it() द्वारा कब्जा कर लिया नहीं जा सकता क्योंकि अपवाद it() के दायरे से बाहर फेंक दिया जाता है उत्पन्न करता है।

आपके द्वारा प्रदर्शित किए गए कैप्चर किए गए अपवाद को process.on('uncaughtException') का उपयोग नोड के तहत या ब्राउज़र में window.onerror() का उपयोग करके कैप्चर किया जाता है।

इस समस्या को हल करने के लिए, आपको पहले पैरामीटर के रूप में अपवाद के साथ done() पर कॉल करने के लिए setTimeout() नामक एसिंक्रोनस फ़ंक्शन के भीतर अपवाद को कैप्चर करने की आवश्यकता है। तुम भी कोई पैरामीटर सफलता का संकेत करने के साथ done() कॉल करने की आवश्यकता है, अन्यथा मोचा एक टाइमआउट त्रुटि रिपोर्ट करेंगे क्योंकि आपके परीक्षण समारोह कभी नहीं संकेत होता है कि यह किया गया था:

window.expect = chai.expect; 

describe('my test', function() { 
    it('should do something', function (done) { 
    // done() is provided by it() to indicate asynchronous completion 
    // call done() with no parameter to indicate that it() is done() and successful 
    // or with an error to indicate that it() failed 
    setTimeout(function() { 
     // Called from the event loop, not it() 
     // So only the event loop could capture uncaught exceptions from here 
     try { 
     expect(true).to.equal(false); 
     done(); // success: call done with no parameter to indicate that it() is done() 
     } catch(e) { 
     done(e); // failure: call done with an error Object to indicate that it() failed 
     } 
    }, 100); 
    // returns immediately after setting timeout 
    // so it() can no longer catch exception happening asynchronously 
    } 
} 

अपने सभी प्रकार के परीक्षण पर ऐसा करने से परेशान है और ड्रवाई न करें ताकि आप यह आपके लिए ऐसा करने के लिए एक समारोह प्रदान करना चाहें। check() साथ

function check(done, f) { 
    try { 
    f(); 
    done(); 
    } catch(e) { 
    done(e); 
    } 
} 

अब आप अपने अतुल्यकालिक परीक्षण पुनर्लेखन कर सकते हैं इस प्रकार है::

window.expect = chai.expect; 

describe('my test', function() { 
    it('should do something', function(done) { 
    setTimeout(function() { 
     check(done, function() { 
     expect(true).to.equal(false); 
     }); 
    }, 100); 
    } 
} 
+0

मैंने अपनी पिछली टिप्पणी को हटा दिया जब मुझे एहसास हुआ कि मैं जिस चीज के बारे में शिकायत कर रहा था (सेटटाइमआउट) वास्तव में मेरे प्रश्न से था। माफ़ कीजिये!! –

+1

उपरोक्त उत्तर गलत लगता है। एक असफल उम्मीद तुरंत फेंक देगी और एक सार्थक त्रुटि के साथ परीक्षण को रोक देगा, जटिल कोशिश/पकड़ की कोई आवश्यकता नहीं है। मैंने अभी ब्राउज़र परीक्षण के साथ इसका परीक्षण किया है। – Offirmo

+0

यह बाद के संस्करण में तय किया गया हो सकता है, उत्तर दो साल पहले प्रश्न में उजागर वास्तविक मुद्दे से संबंधित है। क्या आपने उत्तर परीक्षण कोड चलाने की कोशिश की है? मोचा और चाई का कौन सा संस्करण आप उपयोग कर रहे हैं? –

2

मैंने मोचा मेलिंग सूची में वही बात पूछा। वे मूल रूप से मुझे इस से कहा:

  • हमेशा हमेशा done() के साथ परीक्षण खत्म if (err) done(err);
  • साथ परीक्षण शुरू: मोचा और चाय के साथ अतुल्यकालिक परीक्षण लिखने के लिए।

यह मेरी समस्या का हल हुआ, और बीच में मेरे कोड की एक पंक्ति (अन्य के बीच चाई ​​उम्मीदों) को नहीं बदला। setTimout एसिंक परीक्षण करने का तरीका नहीं है।

यहां link to the discussion in the mailing list है।

+1

आपके द्वारा लिंक की गई चर्चा सर्वर-साइड चाई और मोचा के बारे में है। पोस्टर ** ब्राउज़र-पक्ष ** मोचा और चाई के बारे में पूछ रहा है। –

+0

यह एक ही मुद्दा नहीं है। इस प्रश्न में उदाहरण के रूप में उपयोग किए गए 'setTimeout' फ़ंक्शन को इसके कॉलबैक में कोई त्रुटि नहीं है। – Sylvain

13

तुमने वादा पसंद है, कोशिश Chai as Promised + Q, जो कुछ इस तरह की अनुमति देने के: चलो इस समारोह check() कहते हैं

doSomethingAsync().should.eventually.equal("foo").notify(done); 
-2

मेरे लिए बहुत अच्छा काम किया आईसीएम मोचा/चाई सिनन पुस्तकालय से फर्जी टाइमर था। जहां आवश्यक हो वहां परीक्षण में टाइमर को अग्रिम करें।

var sinon = require('sinon'); 
clock = sinon.useFakeTimers(); 
// Do whatever. 
clock.tick(30000); // Advances the JS clock 30 seconds. 

क्या परीक्षण पूर्ण होने का अतिरिक्त बोनस है।

+1

एसिंक कोड का परीक्षण करते समय मैंने निश्चित रूप से इस तरह के समाधानों का उपयोग करके खुद को पाया है। कॉलबैक मोचा (जैसा कि ऊपर जीन विन्सेंट के उत्तर में दिखाया गया है) के रूप में "किया गया" अच्छा है, लेकिन जब आप इसका उपयोग नहीं करते हैं तो आमतौर पर परीक्षण लिखना आसान होता है। –

1

मैंने एक पैकेज प्रकाशित किया है जो इस समस्या को हल करता है।

npm install --save check-chai

अपने परीक्षण में फिर

, chai.use(checkChai); उपयोग करना और फिर chai.check सहायक फ़ंक्शन का उपयोग करें जिन्हें आप नीचे देख:

पहले check-chai पैकेज स्थापित

var chai = require('chai'); 
var dirtyChai = require('dirty-chai'); 
var checkChai = require('check-chai'); 
var expect = chai.expect; 
chai.use(dirtyChai); 
chai.use(checkChai); 

describe('test', function() { 

    it('should do something', function(done) { 

    // imagine you have some API call here 
    // and it returns (err, res, body) 
    var err = null; 
    var res = {}; 
    var body = {}; 

    chai.check(done, function() { 
     expect(err).to.be.a('null'); 
     expect(res).to.be.an('object'); 
     expect(body).to.be.an('object'); 
    }); 

    }); 

}); 

प्रति Is there a way to get Chai working with asynchronous Mocha tests? मैं इस प्रकाशित के रूप में एक एनपीएम पैकेज।

अधिक जानकारी के लिए कृपया https://github.com/niftylettuce/check-chai देखें।

12

यहां ES6/ES2015 वादे और ES7/ES2016 async/प्रतीक्षा के लिए मेरे पासिंग परीक्षण हैं। उम्मीद है कि यह इस विषय पर शोध किसी के लिए भी एक अच्छा अद्यतन उत्तर प्रदान करता है:

import { expect } from 'chai' 

describe('Mocha',() => { 
    it('works synchronously',() => { 
    expect(true).to.equal(true) 
    }) 

    it('works ansyncronously', done => { 
    setTimeout(() => { 
     expect(true).to.equal(true) 
     done() 
    }, 4) 
    }) 

    it('throws errors synchronously',() => { 
    return true 
    throw new Error('it works') 
    }) 

    it('throws errors ansyncronously', done => { 
    setTimeout(() => { 
     return done() 
     done(new Error('it works')) 
    }, 4) 
    }) 

    it('uses promises',() => { 
    var testPromise = new Promise((resolve, reject) => { 
     setTimeout(() => { 
     resolve('Hello') 
     }, 4) 
    }) 

    testPromise.then(result => { 
     expect(result).to.equal('Hello') 
    }, reason => { 
     throw new Error(reason) 
    }) 
    }) 

    it('uses es7 async/await', async (done) => { 
    const testPromise = new Promise((resolve, reject) => { 
     setTimeout(() => { 
     resolve('Hello') 
     }, 4) 
    }) 

    try { 
     const result = await testPromise 
     expect(result).to.equal('Hello') 
     done() 
    } catch(err) { 
     done(err) 
    } 
    }) 

    /* 
    * Higher-order function for use with async/await (last test) 
    */ 
    const mochaAsync = fn => { 
    return async (done) => { 
     try { 
     await fn() 
     done() 
     } catch (err) { 
     done(err) 
     } 
    } 
    } 

    it('uses a higher order function wrap around async', mochaAsync(async() => { 
    const testPromise = new Promise((resolve, reject) => { 
     setTimeout(() => { 
     resolve('Hello') 
     }, 4) 
    }) 

    expect(await testPromise).to.equal('Hello') 
    })) 
}) 
+0

@ पेड्रो आर। मैं वादा परीक्षण से हटा दिया गया। जैसा कि आपने बताया, इसकी आवश्यकता नहीं है। – RichardForrester

0

मैं इसे एक समारोह को try/catch निकालने को हल किया।

function asyncExpect(test, done){ 
    try{ 
     test(); 
     done(); 
    } catch(error){ 
     done(error); 
    } 
} 

फिर it() में मैं फोन:

it('shall update a host', function (done) { 
      testee.insertHost({_id: 'host_id'}) 
       .then(response => { 
        asyncExpect(() => { 
         expect(response).to.have.property('ok', 1); 
         expect(response).to.have.property('nModified', 1); 
        }, done); 
       }); 

     }); 

यह भी debugable है।

0

@richardforrester http://staxmanade.com/2015/11/testing-asyncronous-code-with-mochajs-and-es7-async-await/ द्वारा प्रदान किए गए इस लिंक के आधार पर, यदि आप किए गए पैरामीटर को छोड़ देते हैं तो वर्णन एक वादा किए गए वादे का उपयोग कर सकते हैं।

केवल डाउनसाइड वहां एक वादा होना है, कोई एसिंक फ़ंक्शन नहीं है (आप इसे वादा के साथ लपेट सकते हैं)। लेकिन इस मामले में, कोड बहुत कम किया जा सकता है।

यह से या तो प्रारंभिक funcThatReturnsAPromise समारोह या उम्मीदों में खाता असफलताओं में ले जाता है:

it('should test Promises', function() { // <= done removed 
    return testee.funcThatReturnsAPromise({'name': 'value'}) // <= return added 
     .then(response => expect(response).to.have.property('ok', 1)); 
}); 
-2

आप डोमेन मॉड्यूल का उपयोग कर सकते हैं। उदाहरण के लिए:

var domain = require('domain').create(); 

domain.run(function() 
{ 
    // place you code here 
}); 

domain.on('error',function(error){ 
    // do something with error or simply print it 
}); 
1

chaiAs समझौता करने का प्रयास करें!

expect(asyncToResultingValue()).to.eventually.equal(true)

Can confirm, मोचा + चाय के लिए बहुत अच्छी तरह से काम करता है: से उत्कृष्ट नामित होने के अलावा, आप जैसे बयानों का उपयोग कर सकते हैं।

https://github.com/domenic/chai-as-promised

1

बहुत ज्यादा से संबंधित और Jean Vincent's answer से प्रेरित है, हम उसकी check समारोह के लिए इसी तरह एक सहायक समारोह को रोजगार, लेकिन हम इसे बजाय फोन eventually (इस में मदद करता है यह चाय-जैसे- का नामकरण सम्मेलनों के साथ मेल वादा किया था)। यह एक ऐसा फ़ंक्शन देता है जो किसी भी संख्या में तर्क लेता है और उन्हें मूल कॉलबैक में भेज देता है। यह आपके परीक्षणों में एक अतिरिक्त नेस्टेड फ़ंक्शन ब्लॉक को खत्म करने में मदद करता है और आपको किसी भी प्रकार के एसिंक कॉलबैक को संभालने की अनुमति देता है।यहाँ यह ES2015 में लिखा है:

function eventually(done, fn) { 
    return (...args) => { 
    try { 
     fn(...args); 
     done(); 
    } catch (err) { 
     done(err); 
    } 
    }; 
}; 

उदाहरण उपयोग:

describe("my async test", function() { 
    it("should fail", function(done) { 
    setTimeout(eventually(done, (param1, param2) => { 
     assert.equal(param1, "foo"); // this should pass 
     assert.equal(param2, "bogus"); // this should fail 
    }), 100, "foo", "bar"); 
    }); 
}); 
संबंधित मुद्दे

 संबंधित मुद्दे