अपवाद के प्रकार का पता लगाने के लिए मैं Assert.Throws का उपयोग कैसे करूं?


247

मैं Assert.Throwsअपवाद के प्रकार और वास्तविक संदेश के शब्दों को मुखर करने के लिए कैसे उपयोग करता हूं ।

कुछ इस तरह:

Assert.Throws<Exception>(
    ()=>user.MakeUserActive()).WithMessage("Actual exception message")

मैं जिस विधि का परीक्षण कर रहा हूं वह एक ही प्रकार के कई संदेशों को अलग-अलग संदेशों के साथ फेंकती है, और मुझे यह परीक्षण करने का तरीका चाहिए कि संदर्भ के आधार पर सही संदेश फेंका जाए।

जवाबों:


444

Assert.Throws जो अपवाद फेंका गया है उसे लौटाता है जो आपको अपवाद पर जोर देता है।

var ex = Assert.Throws<Exception>(() => user.MakeUserActive());
Assert.That(ex.Message, Is.EqualTo("Actual exception message"));

इसलिए यदि कोई अपवाद नहीं फेंका गया है, या गलत प्रकार का अपवाद फेंका गया है, तो पहला Assert.Throwsदावा विफल हो जाएगा। हालाँकि यदि सही प्रकार का अपवाद फेंका जाता है तो अब आप उस वास्तविक अपवाद पर जोर दे सकते हैं जिसे आपने चर में सहेजा है।

इस पैटर्न का उपयोग करके आप अपवाद संदेश के अलावा अन्य चीजों पर जोर दे सकते हैं, उदाहरण के लिए ArgumentExceptionऔर डेरिवेटिव के मामले में , आप यह मान सकते हैं कि पैरामीटर नाम सही है:

var ex = Assert.Throws<ArgumentNullException>(() => foo.Bar(null));
Assert.That(ex.ParamName, Is.EqualTo("bar"));

आप इन मुखर को करने के लिए धाराप्रवाह एपीआई का उपयोग कर सकते हैं:

Assert.That(() => foo.Bar(null), 
Throws.Exception
  .TypeOf<ArgumentNullException>()
  .With.Property("ParamName")
  .EqualTo("bar"));

या वैकल्पिक रूप से

Assert.That(
    Assert.Throws<ArgumentNullException>(() =>
        foo.Bar(null)
    .ParamName,
Is.EqualTo("bar"));

अपवाद संदेशों पर जोर देते समय थोड़ा टिप SetCultureAttributeयह सुनिश्चित करने के लिए परीक्षण विधि को सजाने के लिए है कि फेंक दिया गया संदेश अपेक्षित संस्कृति का उपयोग कर रहा है। यदि आप स्थानीयकरण की अनुमति देने के लिए संसाधनों के रूप में अपने अपवाद संदेशों को संग्रहीत करते हैं तो यह खेल में आता है।


यह मेरे लिए वास्तव में मददगार था - मैं त्रुटि प्रदर्शित करने का एक तरीका चाहता था, मैंने यह भी नहीं पढ़ा कि क्या कोई मान Assert.Throws विधि द्वारा वापस किया गया था। धन्यवाद
हारून

6
+1 आपको धाराप्रवाह एपीआई दिखाने के लिए धन्यवाद, किसी कारण से मुझे यह समझने में समस्या हो रही थी कि इसे केवल NUnit दस्तावेजों से कैसे उपयोग किया जाए।
एल्सज़ोव्का

जब आप संदेश को मुखर करना चाहते हैं, तो आप सीधे "संपत्ति" के बजाय संदेश संपत्ति का उपयोग भी कर सकते हैं।
मार्सेल

25

अब आप ExpectedExceptionविशेषताओं का उपयोग कर सकते हैं , जैसे

[Test]
[ExpectedException(typeof(InvalidOperationException), 
 ExpectedMessage="You can't do that!"]
public void MethodA_WithNull_ThrowsInvalidOperationException()
{
    MethodA(null);
}

2
इसने मुझे थोड़ा परेशान किया जब पहली बार देखा, क्योंकि परीक्षण में स्पष्ट नहीं था, जो मेरे लिए एक गंध था। यह एक अच्छी सुविधा है, लेकिन किसी को टीम व्हीटर में चर्चा करनी चाहिए, जिसके कारण इसे Assert.Throws पर इस्तेमाल किया जाना चाहिए
Marcel

14
अपवादों के परीक्षण के लिए +1 भी एक अच्छा तरीका है। इसके बारे में ध्यान रखने वाली एकमात्र बात यह है कि सैद्धांतिक रूप से उस संदेश के साथ InvalidOperationException फेंकने वाले कोड की कोई भी रेखा परीक्षण को पास करेगी, जिसमें आपके परीक्षण में कोड भी शामिल है जो परीक्षण डेटा / ऑब्जेक्ट या किसी अन्य विधि को तैयार करता है जिसे आपको पहले निष्पादित करने की आवश्यकता हो सकती है। एक आप परीक्षण में रुचि रखते हैं, संभवतः एक झूठी सकारात्मक में जिसके परिणामस्वरूप। बेशक, यह निर्भर करता है कि संदेश कितना विशिष्ट है और आप किस प्रकार का अपवाद परीक्षण कर रहे हैं। साथ Assert.Throwआप सटीक लाइन लक्षित कर सकते हैं में रुचि रखते हैं।
नहीं

21
ExpectedException विशेषता को NUnit 3 में चित्रित किया गया है: github.com/nunit/docs/wiki/Breaking-Changes
फ्रैंक सेबस्टी

13
Assert.That(myTestDelegate, Throws.ArgumentException
    .With.Property("Message").EqualTo("your argument is invalid."));

2
Nameof ऑपरेटर की शुरुआत के साथ, मैं इस उत्कृष्ट anwser को संपादित करूँगा:Assert.That(myTestDelegate, Throws.ArgumentException .With.Property(nameof(ArgumentException.Message)).EqualTo("your argument is invalid."));
Samuel

@Samuel संपादित करने से एक जोरदार टाइप किए गए संदर्भ का उपयोग होता है, जो अच्छा है, लेकिन दूसरी ओर, यह एक अत्यंत निम्न-गुण वाली संपत्ति का नाम है और मैजिक स्ट्रिंग प्रवाह को बेहतर बनाता है। स्वाद का एक मामला मुझे लगता है
जॉर्डन मॉरिस

1
मैं आपसे पूरी तरह सहमत हूं Exception.Message। मैं अभी भी कम से कम इस विकल्प को जोड़ने की सिफारिश करूंगा क्योंकि With.Propertyइसका उपयोग अन्य वस्तुओं पर भी किया जा सकता है, जो इस मामले में कोड की स्थिरता में सुधार करेंगे।
सैमुअल

5

यह पुराने उत्तर के साथ एक पुराना अभी तक प्रासंगिक प्रश्न है इसलिए मैं वर्तमान समाधान जोड़ रहा हूं:

public void Test() {
    throw new MyCustomException("You can't do that!");
}

[TestMethod]
public void ThisWillPassIfExceptionThrown()
{
    var exception = Assert.ThrowsException<MyCustomException>(
        () => Test(),
        "This should have thrown!");
    Assert.AreEqual("You can't do that!", exception.Message);
}

इसके साथ काम करता है using Microsoft.VisualStudio.TestTools.UnitTesting;


मैं वास्तव में हैरान था कि यह बताने का कोई संक्षिप्त तरीका नहीं था कि एक विधि JUnit की तरह एक अपवाद फेंकता है। जब तक कि निहितार्थ नहीं हैं, मुझे इसकी जानकारी नहीं है, यह संभवतः वर्तमान में सबसे अधिक प्रासंगिक उत्तर है।
नेग्रांनाइट

3

लगातार उत्तर देने के लिए और NUnit की अधिक कार्यक्षमता प्रदान करने के लिए, आप यह कर सकते हैं:

public bool AssertThrows<TException>(
    Action action,
    Func<TException, bool> exceptionCondition = null)
    where TException : Exception 
{
    try
    {
        action();
    }
    catch (TException ex)
    {
        if (exceptionCondition != null)
        {
            return exceptionCondition(ex);
        }

        return true;
    }
    catch
    {
        return false;
    }

    return false; 
}

उदाहरण:

// No exception thrown - test fails.
Assert.IsTrue(
    AssertThrows<InvalidOperationException>(
        () => {}));

// Wrong exception thrown - test fails.
Assert.IsTrue(
    AssertThrows<InvalidOperationException>(
        () => { throw new ApplicationException(); }));

// Correct exception thrown - test passes.
Assert.IsTrue(
    AssertThrows<InvalidOperationException>(
        () => { throw new InvalidOperationException(); }));

// Correct exception thrown, but wrong message - test fails.
Assert.IsTrue(
    AssertThrows<InvalidOperationException>(
        () => { throw new InvalidOperationException("ABCD"); },
        ex => ex.Message == "1234"));

// Correct exception thrown, with correct message - test passes.
Assert.IsTrue(
    AssertThrows<InvalidOperationException>(
        () => { throw new InvalidOperationException("1234"); },
        ex => ex.Message == "1234"));

2

इस मुद्दे को उठाए हुए एक लंबा समय हो गया है, मुझे एहसास है, लेकिन मैं हाल ही में एक ही चीज़ में भाग गया, और MSTest के लिए इस फ़ंक्शन का सुझाव देता हूं:

public bool AssertThrows(Action action) where T : Exception 
{ 
try {action();} 
catch(Exception exception) 
{ 
    if (exception.GetType() == typeof(T)) return true; 
} 
return false; 
}

उपयोग:

Assert.IsTrue(AssertThrows<FormatException>(delegate{ newMyMethod(MyParameter); }));

यहाँ और अधिक: http://phejndorf.wordpress.com/2011/02/21/assert-that-a-particular-exception-has-occured/


2

चूंकि मैं कुछ नए NUnit पैटर्नों की वाचालता से परेशान हूं, इसलिए मैं कोड बनाने के लिए कुछ इस तरह का उपयोग करता हूं जो मेरे लिए व्यक्तिगत रूप से क्लीनर है:

public void AssertBusinessRuleException(TestDelegate code, string expectedMessage)
{
    var ex = Assert.Throws<BusinessRuleException>(code);
    Assert.AreEqual(ex.Message, expectedMessage);
}

public void AssertException<T>(TestDelegate code, string expectedMessage) where T:Exception
{
    var ex = Assert.Throws<T>(code);
    Assert.AreEqual(ex.Message, expectedMessage);
}

उपयोग तब है:

AssertBusinessRuleException(() => user.MakeUserActive(), "Actual exception message");

1
TestDelegate क्या है?
रेगेगुएटर

1
यह आपको एक पैरामीटर के रूप में निष्पादित करने के लिए कोड को पारित करने की अनुमति देता है। यह NUnit ढांचे में एक वर्ग है (v3.2.0.0)।
सैवेज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.