कैसे एक परीक्षण लिखने के लिए जो एक त्रुटि जैस्मीन में फेंकने की उम्मीद करता है?


490

मैं जैस्मीन टेस्ट फ्रेमवर्क के लिए एक परीक्षण लिखने की कोशिश कर रहा हूं जो एक त्रुटि की उम्मीद करता है। फिलहाल मैं GitHub से एक जैस्मीन Node.js एकीकरण का उपयोग कर रहा हूं ।

मेरे नोड मॉड्यूल में मेरे पास निम्नलिखित कोड हैं:

throw new Error("Parsing is not possible");

अब मैं एक परीक्षण लिखने की कोशिश करता हूं जो इस त्रुटि की उम्मीद करता है:

describe('my suite...', function() {
    [..]
    it('should not parse foo', function() {
    [..]
        expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));
    });
});

मैंने भी कोशिश की Error()और कुछ अन्य वेरिएंट और बस यह पता नहीं लगा सकता कि इसे कैसे काम करना है।


4
अनाम फ़ंक्शन का उपयोग किए बिना परीक्षण किए गए फ़ंक्शन के तर्क पास करने के लिए, प्रयास करें Function.bind: stackoverflow.com/a/13233194/294855
Danyal Aytekin

जवाबों:


802

आपको expect(...)कॉल में एक फ़ंक्शन पास करना चाहिए । यहाँ आपके पास कोड है:

// incorrect:
expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));

वास्तव में करने की कोशिश कर रहा है parser.parse(raw) में परिणाम पारित करने के प्रयास कॉलexpect(...) ,

इसके बजाय एक अनाम फ़ंक्शन का उपयोग करने का प्रयास करें:

expect( function(){ parser.parse(raw); } ).toThrow(new Error("Parsing is not possible"));

28
यदि आपको भी तर्क पारित करने की आवश्यकता नहीं है, तो आप केवल उम्मीद करने के लिए फ़ंक्शन भी पास कर सकते हैं:expect(parser.parse).toThrow(...)
प्रस्तुत

60
सहायक टिप: आप बस कॉल कर सकते हैं expect(blah).toThrow()। कोई भी तर्क का मतलब यह देखने के लिए नहीं है कि यह बिल्कुल फेंकता है। कोई स्ट्रिंग मिलान आवश्यक नहीं है। इन्हें भी देखें: stackoverflow.com/a/9525172/1804678
Jess

1
मेरी राय में, अनाम फ़ंक्शन में लपेटते समय परीक्षण के इरादे के रूप में यह अधिक स्पष्ट है। इसके अलावा, यह सभी परीक्षणों के बीच सुसंगत रहता है, उदाहरण के लिए, आपको इसे फेंकने के लिए लक्ष्य फ़ंक्शन के मापदंडों को पास करना होगा।
Beez

10
@ प्रकाशित: यह सामान्य रूप से काम नहीं करता है! यदि parser.parseउपयोग किया जाता है this, तो बिना संदर्भ के इसे पारित करने से अप्रत्याशित परिणाम प्राप्त होंगे। आप पास कर सकते हैं parser.parse.bind(parser), लेकिन ईमानदारी से ... एक अनाम फ़ंक्शन अधिक सुरुचिपूर्ण होगा।
मेल्वेंस

2
@LanceKind को नेक्रो के लिए खेद है, लेकिन, आपके पास एक फ़ंक्शन पास करने का कारण यह है कि मूल्य का मूल्यांकन किया जाएगा और इससे पहले कि यह अपेक्षा में पारित किया गया था, एक अपवाद फेंक दें।
1gassitude

68

आप उपयोग कर रहे हैं:

expect(fn).toThrow(e)

लेकिन अगर आप फ़ंक्शन टिप्पणी पर एक नज़र रखेंगे (उम्मीद है कि स्ट्रिंग है):

294 /**
295  * Matcher that checks that the expected exception was thrown by the actual.
296  *
297  * @param {String} expected
298  */
299 jasmine.Matchers.prototype.toThrow = function(expected) {

मुझे लगता है कि आपको शायद इसे इस तरह लिखना चाहिए (लैम्ब्डा - अनाम फ़ंक्शन का उपयोग करके):

expect(function() { parser.parse(raw); } ).toThrow("Parsing is not possible");

यह निम्नलिखित उदाहरण में पुष्टि की गई है:

expect(function () {throw new Error("Parsing is not possible")}).toThrow("Parsing is not possible");

डगलस क्रॉफोर्ड ने "थ्रो न्यू एरर ()" (प्रोटोटाइप तरीका) का उपयोग करने के बजाय, इस दृष्टिकोण की जोरदार सिफारिश की:

throw {
   name: "Error",
   message: "Parsing is not possible"
}

3
वास्तव में कोड को देखते हुए थ्रू खुशी से एक अपवाद वस्तु / या / एक स्ट्रिंग ले जाएगा। उदाहरण के लिए यह अपेक्षित कॉल कर रहा है कॉल की जाँच करें।
पीट हॉजसन ने

1
यह स्ट्रिंग को बिना संदेश संपत्ति वाले स्ट्रिंग प्रभाव के साइड इफेक्ट के रूप में अनुमति देता है
एमपीपीस

1
बहुत बहुत धन्यवाद जो काम किया। मैं अभी भी, पीट का जवाब स्वीकार कर लिया क्योंकि उसके जवाब यह मेरे लिए और अधिक स्पष्ट रूप बनाया है, मुझे लगता है कि है एक लैम्ब्डा उपयोग करने के लिए। फिर भी +1 :-) धन्यवाद!
ईकोक्स

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

2
@kybernetikos आश्चर्यजनक रूप से, पूरी तरह से सच नहीं है; यदि आप एक गैर- Error( jsfiddle.net/k1mxey8j ) फेंकते हैं, तो भी आपको क्रोम कंसोल में एक स्टैक ट्रेस मिलेगा । हालाँकि, आपकी फेंकी गई वस्तु में निश्चित रूप से .stackसंपत्ति नहीं होगी , जो महत्वपूर्ण हो सकती है यदि आप स्वचालित त्रुटि रिपोर्टिंग सेट करना चाहते हैं ।
मार्क अमेरी

24

एक अनाम फ़ंक्शन बनाने से अधिक सुरुचिपूर्ण समाधान जो एकमात्र उद्देश्य दूसरे को लपेटना है, es5 के bindफ़ंक्शन का उपयोग करना है। बाइंड फ़ंक्शन एक नया फ़ंक्शन बनाता है, जिसे जब कॉल किया जाता है, तो उसका हैthis कीवर्ड को प्रदान किए गए मान पर सेट किसी नए फ़ंक्शन को कॉल किए जाने पर प्रदान किए गए किसी भी तर्क से पहले दिए गए अनुक्रम के साथ।

के बजाय:

expect(function () { parser.parse(raw, config); } ).toThrow("Parsing is not possible");

विचार करें:

expect(parser.parse.bind(parser, raw, config)).toThrow("Parsing is not possible");

बाइंड सिंटेक्स आपको विभिन्न thisमूल्यों के साथ फ़ंक्शन का परीक्षण करने की अनुमति देता है , और मेरी राय में परीक्षण को अधिक पठनीय बनाता है। इसे भी देखें: https://stackoverflow.com/a/13233194/1248889


23

मैं निम्नलिखित के साथ जैस्मीन के टूथो मैचर की जगह लेता हूं, जो आपको अपवाद की संपत्ति या उसकी संदेश संपत्ति पर मेल खाने देता है। मेरे लिए यह लिखना आसान है और कम भंगुर है, जैसा कि मैं निम्नलिखित कर सकता हूं:

throw {
   name: "NoActionProvided",
   message: "Please specify an 'action' property when configuring the action map."
}

और फिर निम्नलिखित के साथ परीक्षण करें:

expect (function () {
   .. do something
}).toThrow ("NoActionProvided");

यह मुझे अपवाद संदेश को बाद में परीक्षणों को तोड़ने के बिना, जब महत्वपूर्ण बात यह है कि यह अपवाद के अपेक्षित प्रकार को फेंक देता है।

यह है कि यह अनुमति देता है के लिए यह प्रतिस्थापन है:

jasmine.Matchers.prototype.toThrow = function(expected) {
  var result = false;
  var exception;
  if (typeof this.actual != 'function') {
    throw new Error('Actual is not a function');
  }
  try {
    this.actual();
  } catch (e) {
    exception = e;
  }
  if (exception) {
      result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected) || this.env.equals_(exception.name, expected));
  }

  var not = this.isNot ? "not " : "";

  this.message = function() {
    if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
      return ["Expected function " + not + "to throw", expected ? expected.name || expected.message || expected : " an exception", ", but it threw", exception.name || exception.message || exception].join(' ');
    } else {
      return "Expected function to throw an exception.";
    }
  };

  return result;
};

4
एक अच्छा तरीका है, लेकिन {name: '...', संदेश: '...'} जावास्क्रिप्ट में एक उचित त्रुटि ऑब्जेक्ट है?
मार्क

1
अच्छी टिप्पणी @Marc। आप सही हैं, नाम संपत्ति मानक नहीं है। developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… , लेकिन क्या यह इतना गलत है?
जेस

4
@Jake! मुझे एक बेहतर तरीका मिल गया !!!! आप बस कॉल कर सकते हैं expect(blah).toThrow()। किसी भी तर्क का मतलब यह देखने के लिए नहीं है कि यह बिल्कुल फेंकता है। कोई स्ट्रिंग मिलान आवश्यक नहीं है। इसे भी देखें: stackoverflow.com/a/9525172/1804678
Jess

5
धन्यवाद जेस - यह सच है, लेकिन फिर यह टाइपएयरर की तरह कुछ अन्य त्रुटि को फेंक सकता है, और मेरा परीक्षण गलत तरीके से पास होगा, एक असली बग को मास्किंग।
जेक

4
अब आप एक RegEx का उपयोग एक तर्क के रूप में tohhrow () के लिए भी कर सकते हैं।
टोनी ओ'हागन

21

जैसा कि पहले उल्लेख किया गया है, एक फ़ंक्शन को पास करने की आवश्यकता है toThrowक्योंकि यह वह फ़ंक्शन है जिसका आप अपने परीक्षण में वर्णन कर रहे हैं: "मुझे उम्मीद है कि यह फ़ंक्शन 3 फेंक देगा"

expect(() => parser.parse(raw))
  .toThrow(new Error('Parsing is not possible'));

यदि जैस्मीन-मैचर्स का उपयोग करते हैं, तो आप निम्न में से एक का उपयोग कर सकते हैं जब वे स्थिति के अनुरूप हों;

// I just want to know that an error was
// thrown and nothing more about it
expect(() => parser.parse(raw))
  .toThrowAnyError();

या

// I just want to know that an error of 
// a given type was thrown and nothing more
expect(() => parser.parse(raw))
  .toThrowErrorOfType(TypeError);

3
यह expect(foo).toThrowError(TypeError);जैस्मीन 2.5 में है: चमेली। जीथूब ।io
बेनी न्युगबॉएर

9

मुझे पता है कि अधिक कोड है, लेकिन आप यह भी कर सकते हैं:

try
   do something
   @fail Error("should send a Exception")
 catch e
   expect(e.name).toBe "BLA_ERROR"
   expect(e.message).toBe 'Message'

मैं 'सेल्फ-डॉक्यूमेंटिंग' पहलू को पसंद करता हूं ... यह बहुत स्पष्ट करता है कि आप एक एरर स्टेट का परीक्षण कर रहे हैं
JRulle

6

ताबूत प्रेमियों के लिए

expect( => someMethodCall(arg1, arg2)).toThrow()

3

जो कोई भी अभी भी इस समस्या का सामना कर रहा है, मेरे लिए पोस्ट किया गया समाधान काम नहीं आया और यह इस त्रुटि को दूर करता Error: Expected function to throw an exception. रहा : मुझे बाद में एहसास हुआ कि जिस समारोह में मैं एक त्रुटि फेंकने की उम्मीद कर रहा था वह एक async फ़ंक्शन था और यह वादा करने की उम्मीद कर रहा था अस्वीकार कर दिया जाए और फिर त्रुटि फेंके और यही मैं अपने कोड में कर रहा था:

throw new Error('REQUEST ID NOT FOUND');

और मैंने अपने परीक्षण में जो कुछ किया, वह काम किया:

it('Test should throw error if request not found', willResolve(() => {
         const promise = service.getRequestStatus('request-id');
                return expectToReject(promise).then((err) => {
                    expect(err.message).toEqual('REQUEST NOT FOUND');
                });
            }));

इसके लिए धन्यवाद। मैं बहुत उलझन में था, लेकिन आपकी टिप्पणी सही समझ में आती है। मैंने नए expectAsync jasmine.github.io/api/3.3/async-matchers.html
बेंजामिन

0
  • जब आप सेवाओं का परीक्षण mocking mechanismकरने के लिए उपयोग कर सकते हैं ।
  • नकली बनाने के लिए NgModule प्रदाताओं खंड का लाभ उठाएं ।

  • वर्णन में (),

providers: [{ provide: APIService, useValue: { api: { filterTaskDetails: () => throwError('Error') }}}]

throwErrorसे आयात किया जाना है rxjs

  • अपेक्षा में () ब्लॉक परीक्षण के रूप में,
spyOn(component['toaster'], 'showError');
/** add respected it() blocks**/
expect(component['toaster'].showError).toHaveBeenCalledTimes(1);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.