তারা নিক্ষেপ করা হবে তা নিশ্চিত করার জন্য আসর্টের সাথে ব্যতিক্রমগুলি পরীক্ষা করার সর্বোত্তম উপায়


99

আপনি কি মনে করেন যে ব্যতিক্রমগুলি পরীক্ষার জন্য এটি একটি ভাল উপায়? কোনও পরামর্শ?

Exception exception = null;
try{
    //I m sure that an exeption will happen here
}
catch (Exception ex){
    exception = ex;
}

Assert.IsNotNull(exception);

আমি এমএস টেস্ট ব্যবহার করছি।

উত্তর:


139

আমার ব্যবহার করা বিভিন্ন ধরণের ধরণ রয়েছে। ExpectedExceptionযখন ব্যতিক্রম প্রত্যাশিত হয় তখন আমি বেশিরভাগ সময় অ্যাট্রিবিউটটি ব্যবহার করি । এটি বেশিরভাগ ক্ষেত্রেই যথেষ্ট, তবে কিছু ক্ষেত্রে রয়েছে যখন এটি পর্যাপ্ত নয়। ব্যতিক্রম ক্যাপচারযোগ্য নয় - যেহেতু এটি এমন একটি পদ্ধতি দ্বারা ছুঁড়েছে যা প্রতিবিম্ব দ্বারা ডাকা হয় - বা সম্ভবত আমি কেবল অন্যান্য শর্তগুলি পরীক্ষা করে দেখতে চাই, বলুন যে কোনও লেনদেন পিছনে ফিরে গেছে বা কিছু মান এখনও সেট করা আছে। এই ক্ষেত্রেগুলিতে আমি এটিকে একটি try/catchব্লকে মুড়িয়ে রাখি যা সঠিক ব্যতিক্রমটি প্রত্যাশা করে, Assert.Failকোডটি সফল হয় এবং একটি আলাদা ব্যতিক্রম ছুঁড়ে না যায় তা নিশ্চিত করার জন্য জেনেরিক ব্যতিক্রমগুলিও ক্যাচ করে an

প্রথম কেস:

[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void MethodTest()
{
     var obj = new ClassRequiringNonNullParameter( null );
}

দ্বিতীয় মামলা:

[TestMethod]
public void MethodTest()
{
    try
    {
        var obj = new ClassRequiringNonNullParameter( null );
        Assert.Fail("An exception should have been thrown");
    }
    catch (ArgumentNullException ae)
    {
        Assert.AreEqual( "Parameter cannot be null or empty.", ae.Message );
    }
    catch (Exception e)
    {
        Assert.Fail(
             string.Format( "Unexpected exception of type {0} caught: {1}",
                            e.GetType(), e.Message )
        );
    }
}

16
অনেক ইউনিট টেস্টিং ফ্রেমওয়ার্ক ব্যতিক্রম হিসাবে দৃser় ব্যর্থতা প্রয়োগ করে। সুতরাং দ্বিতীয় ক্ষেত্রে Assert.Fail () ধরা পড়বে (ব্যতিক্রম) ব্লক, যা ব্যতিক্রম বার্তাটি আড়াল করবে। আপনাকে একটি ক্যাচ যুক্ত করতে হবে (NUnit.Framework.AssertionException) {নিক্ষেপ;} বা অনুরূপ - আমার উত্তর দেখুন।
গ্রাহামস

@ গ্রাহাম - আমি এটি আমার মাথার উপরের অংশে টাইপ করেছি। সাধারণত আমি ব্যাতিক্রমের বার্তাটি প্রকারের বাইরেও মুদ্রণ করব। মুল বক্তব্যটি হ'ল পরীক্ষাটি ব্যর্থ হবে যেহেতু দ্বিতীয় হ্যান্ডলার দৃser় ব্যর্থতা ধরে ফেলবে এবং ত্রুটি সম্পর্কিত তথ্য দিয়ে "পুনরায় ফিরিয়ে দেবে"।
tvanfosson

4
যদিও আপনার কোডটি কার্যত কার্যকর হয়েছে তবে আমি প্রত্যাশিত এক্সপ্রেশন অ্যাট্রিবিউটটি ব্যবহার করার প্রস্তাব দিই না (যেহেতু এটি খুব জটিল এবং ত্রুটি-প্রবণ) বা প্রতিটি পরীক্ষায় একটি চেষ্টা / ক্যাচ ব্লক লেখার জন্য (যেহেতু এটি খুব জটিল এবং ত্রুটি-প্রবণ)। একটি ভাল-ডিজাইন করা দৃsert় পদ্ধতি ব্যবহার করুন - হয় আপনার পরীক্ষার কাঠামোর দ্বারা সরবরাহ করা হয়েছে বা আপনার নিজের লিখুন। আপনি আরও ভাল কোড অর্জন করতে পারেন এবং পরীক্ষার পরিবর্তন হিসাবে আপনাকে বিভিন্ন কৌশলগুলির মধ্যে বাছাই করতে বা একে অপরকে পরিবর্তন করতে হবে না। স্ট্যাকওভারফ্লো.com
স্টিভ

এফওয়াইআই - আমি এক্স ইউনাইট ব্যবহারের দিকে এগিয়ে গিয়েছি যার একটি দৃ strongly়পদযুক্ত Assert.Throwsপদ্ধতি রয়েছে যা এই দুটি ক্ষেত্রেই covers েকে দেয় ।
tvanfosson

প্রত্যাশিত এক্সসেপশন অ্যাট্রিবিউটটি ব্যতিক্রম ছোঁড়া হয়েছে কিনা তা পরীক্ষা করার অভ্যাস এবং তারিখের উপায়। আমার সম্পূর্ণ উত্তর নীচে দেখুন।
বাইটেডেভ

45

এখন, 2017, আপনি নতুন এমএসটিস্ট ভি 2 ফ্রেমওয়ার্কটি দিয়ে এটি আরও সহজ করতে পারেন :

Assert.ThrowsException<Exception>(() => myClass.MyMethodWithError());

//async version
await Assert.ThrowsExceptionAsync<SomeException>(
  () => myObject.SomeMethodAsync()
);

এটি কেবল তখনই সফল হবে যখন একটি System.Exceptionনিক্ষিপ্ত হয়। অন্য কোনও, যেমন System.ArgumentExceptionপরীক্ষায় ব্যর্থ হবে।
sschoof

4
আপনি যদি অন্য ধরণের ব্যতিক্রম প্রত্যাশা করে থাকেন তবে আপনার এটি পরীক্ষা করা উচিত ... উদাহরণস্বরূপ, আপনি চেঁচামেচি করুন: দৃsert়প্রকাশ
ইকারো বোম্বোনাটো

4
কিছু গুরুত্বপূর্ণ বিষয় লক্ষণীয় হ'ল Assert.ThrowsException<MyException>এটির ব্যবহার সম্পূর্ণরূপে প্রদত্ত ব্যতিক্রম প্রকারের বিরুদ্ধে পরীক্ষা করবে এবং এর কোনও উত্পন্ন ব্যতিক্রম প্রকার নয়। আমার উদাহরণে, যদি পরীক্ষিত Subছিল Throwএকটি MyInheritedException(বেস ক্লাস থেকে উদ্ভূত টাইপ MyException), তারপর পরীক্ষা হবে ব্যর্থ
আমা

আপনি যদি নিজের পরীক্ষাটি প্রসারিত করতে চান এবং ব্যতিক্রমের পাশাপাশি তার উদ্ভূত প্রকারগুলি গ্রহণ করতে চান তবে এ ব্যবহার করুন Try { SubToTest(); Assert.Fail("...") } Catch (AssertFailedException e) {throw;} Catch (MyException e) {...}Catch (AssertFailedException e) {throw;}(Allgeek থেকে সিএফ মন্তব্য) এর সর্বাধিক গুরুত্ব নোট করুন
আমা

16

আমি এখানে নতুন এবং মন্তব্য করা বা ডাউনওয়োট করার খ্যাতি নেই, তবে অ্যান্ডি হোয়াইটের জবাবের উদাহরণে একটি ত্রুটি চিহ্নিত করতে চেয়েছিল :

try
{
    SomethingThatCausesAnException();
    Assert.Fail("Should have exceptioned above!");
}
catch (Exception ex)
{
    // whatever logging code
}

সমস্ত ইউনিট টেস্টিং ফ্রেমওয়ার্কগুলিতে আমি পরিচিত, Assert.Failএকটি ব্যতিক্রম ছুঁড়ে দিয়ে কাজ করে, তাই জেনেরিক ক্যাচটি আসলে পরীক্ষার ব্যর্থতার মুখোশ দেয়। যদি SomethingThatCausesAnException()ছুঁড়ে না ফেলে, Assert.Failউইল, তবে ব্যর্থতা নির্দেশ করতে পরীক্ষার দৌড়াদির কাছে তা কখনই ফুঁসে উঠবে না।

যদি আপনার প্রত্যাশিত ব্যতিক্রম (যেমন, ব্যতিক্রমের বার্তা / বৈশিষ্ট্যের মতো নির্দিষ্ট বিবরণ জোর দেওয়া) ধরার দরকার হয় তবে এটি নির্দিষ্ট ব্যতিক্রমী ধরণেরটি ধরতে হবে, বেস ব্যতিক্রম ব্যতীত নয়। এটি Assert.Failব্যতিক্রমকে বুবলি আউট করার অনুমতি দেবে (ধরে নিলে আপনি যে একই ধরণের ব্যতিক্রম আপনার ইউনিট টেস্টিং ফ্রেমওয়ার্কটি করেন তা ছুঁড়ে ফেলছেন না), তবে এখনও আপনার SomethingThatCausesAnException()পদ্ধতি দ্বারা ছড়িয়ে দেওয়া ব্যতিক্রমটিকে বৈধতা দেওয়ার অনুমতি দেয় ।


16

V 2.5 হিসাবে, Assertব্যতিক্রমগুলি পরীক্ষা করার জন্য নুনিটের নিম্নলিখিত পদ্ধতি-স্তরের গুলি রয়েছে:

Assert.Thes , যা সঠিক ব্যতিক্রম প্রকারের জন্য পরীক্ষা করবে:

Assert.Throws<NullReferenceException>(() => someNullObject.ToString());

এবং Assert.Catch, যা প্রদত্ত প্রকারের ব্যতিক্রম বা এই ধরণের থেকে প্রাপ্ত ব্যাতিক্রমের জন্য পরীক্ষা করবে:

Assert.Catch<Exception>(() => someNullObject.ToString());

একটি সরাইয়া হিসাবে, যখন ইউনিট পরীক্ষা যা ব্যতিক্রম নিক্ষেপ ডিবাগ, আপনার কাছ থেকে বনাম প্রতিরোধ করতে চাইতে পারেন ব্যতিক্রম উপর ভঙ্গ

সম্পাদনা করুন

কেবল নীচে ম্যাথিউর মন্তব্যের উদাহরণ দেওয়ার জন্য, জেনেরিকের ফিরে আসা Assert.Throwsএবং Assert.Catchব্যতিক্রমের ধরণের সাথে ব্যতিক্রম, যা আপনি পরবর্তী তদন্তের জন্য পরীক্ষা করতে পারেন:

// The type of ex is that of the generic type parameter (SqlException)
var ex = Assert.Throws<SqlException>(() => MethodWhichDeadlocks());
Assert.AreEqual(1205, ex.Number);

4
রায় ওশেরোভ আর্ট অফ ইউনিট টেস্টিং-এর দ্বিতীয় সংস্করণ, বিভাগ ২..2.২ এ সুপারিশ করেছেন।
আভি

4
আমি পছন্দ করি Assert.Throws, এছাড়াও এটি ব্যতিক্রমটি ফিরিয়ে দেয় যাতে আপনি ব্যতিক্রম নিজেই আরও জোর লিখে রাখতে পারেন।
ম্যাথু

প্রশ্নটি এমএসটিস্টের পক্ষে ছিল নুনিট নয়।
বাইটেডেভ

@ ন্যাশওয়ান ওপি-র আসল প্রশ্নের সেই যোগ্যতা নেই, এবং ট্যাগিং এখনও এমএস-টেস্টের যোগ্যতা অর্জন করে না। এটি যেমন দাঁড়িয়েছে, এটি একটি সি #,। নেট, ইউনিট-পরীক্ষার প্রশ্ন।
স্টুয়ার্টএলসি

11

দুর্ভাগ্যক্রমে এমস্টেস্ট স্টিলের কেবলমাত্র প্রত্যাশিত এক্সপ্রেশন অ্যাট্রিবিউট আছে (এমএসটিস্ট সম্পর্কে এমএস কতটা যত্নশীল তা দেখায়) যা আইএমও বেশ ভয়ঙ্কর কারণ এটি অ্যারেঞ্জ / অ্যাক্ট / এ্যাসেট প্যাটার্নটি ভেঙে দেয় এবং আপনি ব্যতিক্রমটি প্রত্যাশা করে ঠিক কোন কোডের লাইনটি নির্দিষ্ট করতে দেয় না ঘটতে।

আমি যখন এমএসটিস্ট ব্যবহার করতে (/ ক্লায়েন্ট দ্বারা জোর করে) ব্যবহার করি তখন আমি সর্বদা এই সহায়ক শ্রেণিটি ব্যবহার করি:

public static class AssertException
{
    public static void Throws<TException>(Action action) where TException : Exception
    {
        try
        {
            action();
        }
        catch (Exception ex)
        {
            Assert.IsTrue(ex.GetType() == typeof(TException), "Expected exception of type " + typeof(TException) + " but type of " + ex.GetType() + " was thrown instead.");
            return;
        }
        Assert.Fail("Expected exception of type " + typeof(TException) + " but no exception was thrown.");
    }

    public static void Throws<TException>(Action action, string expectedMessage) where TException : Exception
    {
        try
        {
            action();
        }
        catch (Exception ex)
        {
            Assert.IsTrue(ex.GetType() == typeof(TException), "Expected exception of type " + typeof(TException) + " but type of " + ex.GetType() + " was thrown instead.");
            Assert.AreEqual(expectedMessage, ex.Message, "Expected exception with a message of '" + expectedMessage + "' but exception with message of '" + ex.Message + "' was thrown instead.");
            return;
        }
        Assert.Fail("Expected exception of type " + typeof(TException) + " but no exception was thrown.");
    }
}

ব্যবহারের উদাহরণ:

AssertException.Throws<ArgumentNullException>(() => classUnderTest.GetCustomer(null));

10

ExpectedExceptionঅ্যাট্রিবিউট ব্যবহারের বিকল্প হিসাবে আমি মাঝে মাঝে আমার পরীক্ষার ক্লাসগুলির জন্য দুটি সহায়ক পদ্ধতি সংজ্ঞায়িত করি:

AssertThrowsException() একটি প্রতিনিধি নেয় এবং দৃ as়ভাবে দাবি করে যে এটি প্রত্যাশিত বার্তা সহ প্রত্যাশিত ব্যতিক্রম ছোঁড়ে।

AssertDoesNotThrowException() একই প্রতিনিধি গ্রহণ করে এবং দৃ it়ভাবে দাবি করে যে এটি কোনও ব্যতিক্রম ছুঁড়ে না।

এই জুড়িটি খুব কার্যকর হতে পারে যখন আপনি পরীক্ষা করতে চান যে এক ক্ষেত্রে ব্যতিক্রম ছুঁড়েছে, তবে অন্যটি নয়।

এগুলি ব্যবহার করে আমার ইউনিট পরীক্ষার কোডটি দেখতে দেখতে দেখতে এটির মতো হতে পারে:

ExceptionThrower callStartOp = delegate(){ testObj.StartOperation(); };

// Check exception is thrown correctly...
AssertThrowsException(callStartOp, typeof(InvalidOperationException), "StartOperation() called when not ready.");

testObj.Ready = true;

// Check exception is now not thrown...
AssertDoesNotThrowException(callStartOp);

সুন্দর এবং ঝরঝরে হাহ?

আমার AssertThrowsException()এবং AssertDoesNotThrowException()পদ্ধতিগুলি নিম্নরূপে একটি সাধারণ বেস শ্রেণিতে সংজ্ঞায়িত করা হয়:

protected delegate void ExceptionThrower();

/// <summary>
/// Asserts that calling a method results in an exception of the stated type with the stated message.
/// </summary>
/// <param name="exceptionThrowingFunc">Delegate that calls the method to be tested.</param>
/// <param name="expectedExceptionType">The expected type of the exception, e.g. typeof(FormatException).</param>
/// <param name="expectedExceptionMessage">The expected exception message (or fragment of the whole message)</param>
protected void AssertThrowsException(ExceptionThrower exceptionThrowingFunc, Type expectedExceptionType, string expectedExceptionMessage)
{
    try
    {
        exceptionThrowingFunc();
        Assert.Fail("Call did not raise any exception, but one was expected.");
    }
    catch (NUnit.Framework.AssertionException)
    {
        // Ignore and rethrow NUnit exception
        throw;
    }
    catch (Exception ex)
    {
        Assert.IsInstanceOfType(expectedExceptionType, ex, "Exception raised was not the expected type.");
        Assert.IsTrue(ex.Message.Contains(expectedExceptionMessage), "Exception raised did not contain expected message. Expected=\"" + expectedExceptionMessage + "\", got \"" + ex.Message + "\"");
    }
}

/// <summary>
/// Asserts that calling a method does not throw an exception.
/// </summary>
/// <remarks>
/// This is typically only used in conjunction with <see cref="AssertThrowsException"/>. (e.g. once you have tested that an ExceptionThrower
/// method throws an exception then your test may fix the cause of the exception and then call this to make sure it is now fixed).
/// </remarks>
/// <param name="exceptionThrowingFunc">Delegate that calls the method to be tested.</param>
protected void AssertDoesNotThrowException(ExceptionThrower exceptionThrowingFunc)
{
    try
    {
        exceptionThrowingFunc();
    }
    catch (NUnit.Framework.AssertionException)
    {
        // Ignore and rethrow any NUnit exception
        throw;
    }
    catch (Exception ex)
    {
        Assert.Fail("Call raised an unexpected exception: " + ex.Message);
    }
}

4

বেশিরভাগ নেট নেট ইউনিট টেস্টিং ফ্রেমওয়ার্কের সাহায্যে আপনি পরীক্ষার পদ্ধতিতে একটি [প্রত্যাশিত ধারণা] বৈশিষ্ট্য রাখতে পারেন। তবে এটি আপনাকে বলতে পারে না যে ব্যতিক্রমটি আপনি প্রত্যাশা করেছেন এমন পর্যায়ে ঘটেছে। Xunit.net সেখানেই সহায়তা করতে পারে।

এক্সুনিটের সাহায্যে আপনার দাবী রয়েছে hআলো, যাতে আপনি এই জাতীয় জিনিসগুলি করতে পারেন:

    [Fact]
    public void CantDecrementBasketLineQuantityBelowZero()
    {
        var o = new Basket();
        var p = new Product {Id = 1, NetPrice = 23.45m};
        o.AddProduct(p, 1);
        Assert.Throws<BusinessException>(() => o.SetProductQuantity(p, -3));
    }

[ঘটনা] হ'ল [টেস্টমেথোড] এর xunit সমতুল্য


যদি আপনাকে অবশ্যই এমএসটিস্ট ব্যবহার করতে হয় (যা আমি প্রায়শই নিয়োগকর্তাদের দ্বারা বাধ্য হয়) তবে নীচে আমার উত্তরটি দেখুন।
বাইটেডে

4

এক্সপেক্টেড এক্সেপশনএট্রিবিউট দিয়ে পরীক্ষাটি চিহ্নিত করুন (এটি নুনিট বা এমএসটিস্টে শব্দটি; অন্যান্য ইউনিট পরীক্ষার কাঠামোর ব্যবহারকারীদের অনুবাদ করার প্রয়োজন হতে পারে)।


প্রত্যাশিত এক্সসেপশনএট্রিবিউট ব্যবহার করবেন না (নীচে আমার পোস্টে দেওয়া কারণ) নুনিটের এ্যাসেটর রয়েছে <
bytedev

0

ব্যবহার করার সুপারিশ NUnit এর পরিষ্কার প্রতিনিধি সিনট্যাক্স।

পরীক্ষার উদাহরণ ArgumentNullExeption:

[Test]
[TestCase(null)]
public void FooCalculation_InvalidInput_ShouldThrowArgumentNullExeption(string text)
{
    var foo = new Foo();
    Assert.That(() => foo.Calculate(text), Throws.ArgumentNullExeption);

    //Or:
    Assert.That(() => foo.Calculate(text), Throws.Exception.TypeOf<ArgumentNullExeption>);
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.