Assert
यह सत्यापित करने के लिए कि मैं (या अन्य टेस्ट क्लास?) का उपयोग कैसे करूं ?
Assert
यह सत्यापित करने के लिए कि मैं (या अन्य टेस्ट क्लास?) का उपयोग कैसे करूं ?
जवाबों:
"विज़ुअल स्टूडियो टीम टेस्ट" के लिए यह प्रतीत होता है कि आप परीक्षण की विधि में ExpectedException विशेषता को लागू करते हैं।
यहाँ प्रलेखन से नमूना: विज़ुअल स्टूडियो टीम टेस्ट के साथ एक इकाई परीक्षण वॉकथ्रू
[TestMethod]
[ExpectedException(typeof(ArgumentException),
"A userId of null was inappropriately allowed.")]
public void NullUserIdInConstructor()
{
LogonInfo logonInfo = new LogonInfo(null, "P@ss0word");
}
आमतौर पर आपके परीक्षण ढांचे के पास इसके लिए एक उत्तर होगा। लेकिन अगर यह पर्याप्त लचीला नहीं है, तो आप हमेशा ऐसा कर सकते हैं:
try {
somethingThatShouldThrowAnException();
Assert.Fail(); // If it gets to this line, no exception was thrown
} catch (GoodException) { }
@ जोंस बताते हैं, आधार को पकड़ने के लिए यह काम नहीं करता है:
try {
somethingThatShouldThrowAnException();
Assert.Fail(); // raises AssertionException
} catch (Exception) {
// Catches the assertion exception, and the test passes
}
यदि आप बिल्कुल अपवाद को पकड़ते हैं, तो आपको Assert.Fail () को पुनर्विचार करने की आवश्यकता है। लेकिन वास्तव में, यह एक संकेत है जिसे आपको हाथ से नहीं लिखना चाहिए; विकल्पों के लिए अपने परीक्षण ढांचे की जांच करें, या देखें कि क्या आप परीक्षण के लिए अधिक सार्थक अपवाद फेंक सकते हैं।
catch (AssertionException) { throw; }
आपको जो कुछ भी पसंद है उसे इस दृष्टिकोण को अनुकूलित करने में सक्षम होना चाहिए - जिसमें यह निर्दिष्ट करना है कि किस प्रकार के अपवादों को पकड़ना है। यदि आप केवल कुछ प्रकारों की अपेक्षा करते हैं, तो catch
ब्लॉक को समाप्त करें :
} catch (GoodException) {
} catch (Exception) {
// not the right kind of exception
Assert.Fail();
}
इसे लागू करने के लिए मेरा पसंदीदा तरीका थ्रोस नामक एक विधि लिखना है, और इसे किसी अन्य Assert विधि की तरह उपयोग करना है। दुर्भाग्यवश, .NET आपको एक स्टैटिक एक्सटेंशन विधि लिखने की अनुमति नहीं देता है, इसलिए आप इस पद्धति का उपयोग नहीं कर सकते हैं जैसे कि यह वास्तव में एस्टर क्लास में निर्मित है; बस एक और MyAssert या ऐसा ही कुछ कहा जाता है। वर्ग इस तरह दिखता है:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace YourProject.Tests
{
public static class MyAssert
{
public static void Throws<T>( Action func ) where T : Exception
{
var exceptionThrown = false;
try
{
func.Invoke();
}
catch ( T )
{
exceptionThrown = true;
}
if ( !exceptionThrown )
{
throw new AssertFailedException(
String.Format("An exception of type {0} was expected, but not thrown", typeof(T))
);
}
}
}
}
इसका मतलब है कि आपकी इकाई परीक्षण इस तरह दिखता है:
[TestMethod()]
public void ExceptionTest()
{
String testStr = null;
MyAssert.Throws<NullReferenceException>(() => testStr.ToUpper());
}
जो आपके बाकी यूनिट टेस्ट सिंटैक्स की तरह दिखता है और बहुत अधिक व्यवहार करता है।
Assert.ThrowsException<T>
और Assert.ThrowsExceptionAsync<T>
देखें blogs.msdn.microsoft.com/visualstudioalm/2017/02/25/…
यदि आप NUNIT का उपयोग करते हैं, तो आप ऐसा कुछ कर सकते हैं:
Assert.Throws<ExpectedException>(() => methodToTest());
आगे इसे मान्य करने के लिए फेंके गए अपवाद को संग्रहीत करना भी संभव है:
ExpectedException ex = Assert.Throws<ExpectedException>(() => methodToTest());
Assert.AreEqual( "Expected message text.", ex.Message );
Assert.AreEqual( 5, ex.SomeNumber);
यदि आप MSTest का उपयोग कर रहे हैं, जिसमें मूल रूप से एक ExpectedException
विशेषता नहीं थी , तो आप ऐसा कर सकते हैं:
try
{
SomeExceptionThrowingMethod()
Assert.Fail("no exception thrown");
}
catch (Exception ex)
{
Assert.IsTrue(ex is SpecificExceptionType);
}
ExpectedException का उपयोग करने से सावधान रहें, क्योंकि यह यहाँ दिखाए गए अनुसार कई नुकसान पहुंचा सकता है:
http://geekswithblogs.net/sdorman/archive/2009/01/17/unit-testing-and-expected-exceptions.aspx
और यहाँ:
http://xunit.github.io/docs/comparisons.html
यदि आपको अपवादों का परीक्षण करने की आवश्यकता है, तो तरीकों पर कम डूबे हुए हैं। आप कोशिश कर सकते हैं {act / fail} catch {assert} विधि का उपयोग करें, जो ऐसे फ्रेमवर्क के लिए उपयोगी हो सकता है जिनके पास ExpectedException के अलावा अपवाद परीक्षणों के लिए प्रत्यक्ष समर्थन नहीं है।
एक बेहतर विकल्प xUnit.NET का उपयोग करना है, जो कि एक बहुत ही आधुनिक, आगे की ओर देखने वाली और एक्स्टेंसिबल यूनिट टेस्टिंग फ्रेमवर्क है जो अन्य सभी गलतियों से सीखा है, और बेहतर हुआ है। ऐसा ही एक सुधार Assert.Throws है, जो अपवादों को मुखर करने के लिए बहुत बेहतर सिंटैक्स प्रदान करता है।
आप xUnit.NET को github पर पा सकते हैं: http://xunit.github.io/
MSTest (v2) में अब Assert.ThrowsException फ़ंक्शन है, जिसका उपयोग इस तरह किया जा सकता है:
Assert.ThrowsException<System.FormatException>(() =>
{
Story actual = PersonalSite.Services.Content.ExtractHeader(String.Empty);
});
आप इसे नगेट के साथ स्थापित कर सकते हैं: Install-Package MSTest.TestFramework
एक परियोजना में, हम इस पर काम कर रहे हैं एक और समाधान है।
पहले मुझे ExpectedExceptionAttribute becuase की तरह यह ध्यान में नहीं आता कि कौन सी विधि कॉल है जो अपवाद का कारण बनी।
मैं इसके बजाय एक सहायक के साथ ऐसा करता हूं।
परीक्षा
[TestMethod]
public void AccountRepository_ThrowsExceptionIfFileisCorrupt()
{
var file = File.Create("Accounts.bin");
file.WriteByte(1);
file.Close();
IAccountRepository repo = new FileAccountRepository();
TestHelpers.AssertThrows<SerializationException>(()=>repo.GetAll());
}
HelperMethod
public static TException AssertThrows<TException>(Action action) where TException : Exception
{
try
{
action();
}
catch (TException ex)
{
return ex;
}
Assert.Fail("Expected exception was not thrown");
return null;
}
नीट, यह नहीं है;)
यह परीक्षण विधि पर एक विशेषता है ... आप Assert का उपयोग नहीं करते हैं। इस तरह दिखता है:
[ExpectedException(typeof(ExceptionType))]
public void YourMethod_should_throw_exception()
आप Nuget का उपयोग करके एक पैकेज डाउनलोड कर सकते हैं: PM> Install-Package MSTestExtensions जो MsTest को nUnit / xUnit की शैली में Assert.Throws () सिंटैक्स जोड़ता है।
उच्च स्तरीय निर्देश: असेंबली को डाउनलोड करें और बेसटेस्ट से विरासत में मिला है और आप Assert.Throws () सिंटैक्स का उपयोग कर सकते हैं ।
थ्रोज़ कार्यान्वयन के लिए मुख्य विधि निम्नानुसार है:
public static void Throws<T>(Action task, string expectedMessage, ExceptionMessageCompareOptions options) where T : Exception
{
try
{
task();
}
catch (Exception ex)
{
AssertExceptionType<T>(ex);
AssertExceptionMessage(ex, expectedMessage, options);
return;
}
if (typeof(T).Equals(new Exception().GetType()))
{
Assert.Fail("Expected exception but no exception was thrown.");
}
else
{
Assert.Fail(string.Format("Expected exception of type {0} but no exception was thrown.", typeof(T)));
}
}
प्रकटीकरण: मैंने इस पैकेज को एक साथ रखा।
अधिक जानकारी: http://www.bradoncode.com/blog/2012/01/asserting-exception-in-mstest-with.html
आप इसे एक सरल-रेखा के साथ प्राप्त कर सकते हैं।
यदि आपका ऑपरेशन foo.bar()
async है:
await Assert.ThrowsExceptionAsync<Exception>(() => foo.bar());
यदि foo.bar()
एसिंक्स नहीं है
Assert.ThrowsException<Exception>(() => foo.bar());
ArgumentException
। यदि आप परीक्षण करने के लिए उन्नत मानदंड रखते हैं, तो पुराना ट्रैप कैच और अपवाद प्रतिक्रिया का परीक्षण अभी भी पसंद किया जाता है, लेकिन यह मेरे बहुत काम आता है!
मैं ExpectedException विशेषता का उपयोग करने की अनुशंसा नहीं करता (क्योंकि यह बहुत अड़चन और त्रुटि-प्रवण है) या प्रत्येक परीक्षण में एक कोशिश / कैच ब्लॉक लिखने के लिए (क्योंकि यह बहुत जटिल और त्रुटि-प्रवण है)। एक अच्छी तरह से डिज़ाइन की गई मुखर पद्धति का उपयोग करें - या तो आपके परीक्षण ढांचे द्वारा प्रदान की गई है या अपना स्वयं का लिखें। यहाँ मैंने जो लिखा और उपयोग किया है।
public static class ExceptionAssert
{
private static T GetException<T>(Action action, string message="") where T : Exception
{
try
{
action();
}
catch (T exception)
{
return exception;
}
throw new AssertFailedException("Expected exception " + typeof(T).FullName + ", but none was propagated. " + message);
}
public static void Propagates<T>(Action action) where T : Exception
{
Propagates<T>(action, "");
}
public static void Propagates<T>(Action action, string message) where T : Exception
{
GetException<T>(action, message);
}
public static void Propagates<T>(Action action, Action<T> validation) where T : Exception
{
Propagates(action, validation, "");
}
public static void Propagates<T>(Action action, Action<T> validation, string message) where T : Exception
{
validation(GetException<T>(action, message));
}
}
उदाहरण का उपयोग करता है:
[TestMethod]
public void Run_PropagatesWin32Exception_ForInvalidExeFile()
{
(test setup that might propagate Win32Exception)
ExceptionAssert.Propagates<Win32Exception>(
() => CommandExecutionUtil.Run(Assembly.GetExecutingAssembly().Location, new string[0]));
(more asserts or something)
}
[TestMethod]
public void Run_PropagatesFileNotFoundException_ForExecutableNotFound()
{
(test setup that might propagate FileNotFoundException)
ExceptionAssert.Propagates<FileNotFoundException>(
() => CommandExecutionUtil.Run("NotThere.exe", new string[0]),
e => StringAssert.Contains(e.Message, "NotThere.exe"));
(more asserts or something)
}
टिप्पणियाँ
सत्यापन कॉलबैक का समर्थन करने के बजाय अपवाद लौटा देना एक उचित विचार है, सिवाय इसके कि ऐसा करने के लिए कॉलिंग सिंटैक्स इस दावे का बहुत ही भिन्न उपयोग करता है जो मैं उपयोग करता है।
दूसरों के विपरीत, मैं 'फेंकता' के बजाय 'प्रोपेगेट्स' का उपयोग करता हूं क्योंकि हम केवल यह परीक्षण कर सकते हैं कि एक कॉल से कोई अपवाद फैलता है या नहीं। हम सीधे परीक्षण नहीं कर सकते कि एक अपवाद फेंक दिया गया है। लेकिन मुझे लगता है कि आप फेंकने के लिए छवि फेंक सकते हैं: फेंक दिया गया और पकड़ा नहीं गया।
अंतिम THOUGHT
इस प्रकार के दृष्टिकोण पर स्विच करने से पहले मैंने एक्सपेक्टेडएक्ससेप्शन विशेषता का उपयोग करने पर विचार किया जब एक परीक्षण केवल अपवाद प्रकार को सत्यापित करता था और अधिक सत्यापन की आवश्यकता होने पर कोशिश / कैच ब्लॉक का उपयोग करता था। लेकिन, न केवल मुझे यह सोचना होगा कि प्रत्येक परीक्षण के लिए किस तकनीक का उपयोग करना है, बल्कि कोड को एक तकनीक से दूसरी तकनीक में बदलना चाहिए क्योंकि आवश्यकतानुसार परिवर्तन करना कोई तुच्छ प्रयास नहीं था। एक सुसंगत दृष्टिकोण का उपयोग मानसिक प्रयास को बचाता है।
इसलिए सारांश में, यह दृष्टिकोण खेल: आसानी से उपयोग, लचीलापन और मजबूती (इसे गलत करना कठिन है)।
@Richiban द्वारा प्रदान किया गया सहायक इसके अलावा महान काम करता है, यह उस स्थिति को नहीं संभालता है जहां एक अपवाद को फेंक दिया जाता है, लेकिन अपेक्षित प्रकार नहीं। निम्नलिखित पते हैं कि:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace YourProject.Tests
{
public static class MyAssert
{
/// <summary>
/// Helper for Asserting that a function throws an exception of a particular type.
/// </summary>
public static void Throws<T>( Action func ) where T : Exception
{
Exception exceptionOther = null;
var exceptionThrown = false;
try
{
func.Invoke();
}
catch ( T )
{
exceptionThrown = true;
}
catch (Exception e) {
exceptionOther = e;
}
if ( !exceptionThrown )
{
if (exceptionOther != null) {
throw new AssertFailedException(
String.Format("An exception of type {0} was expected, but not thrown. Instead, an exception of type {1} was thrown.", typeof(T), exceptionOther.GetType()),
exceptionOther
);
}
throw new AssertFailedException(
String.Format("An exception of type {0} was expected, but no exception was thrown.", typeof(T))
);
}
}
}
}
जब से तुम अन्य परीक्षण वर्गों का उपयोग उल्लेख करते हैं, से एक बेहतर विकल्प ExpectedException
विशेषता का उपयोग करने के लिए है Shoudly के Should.Throw ।
Should.Throw<DivideByZeroException>(() => { MyDivideMethod(1, 0); });
मान लीजिए कि हमारे पास एक आवश्यकता है कि ग्राहक के पास ऑर्डर बनाने के लिए एक पता होना चाहिए । यदि नहीं, तो विधि में परिणाम होना चाहिए । तब हम लिख सकते थे:CreateOrderForCustomer
ArgumentException
[TestMethod]
public void NullUserIdInConstructor()
{
var customer = new Customer(name := "Justin", address := null};
Should.Throw<ArgumentException>(() => {
var order = CreateOrderForCustomer(customer) });
}
यह एक ExpectedException
विशेषता का उपयोग करने से बेहतर है क्योंकि हम इस बारे में विशिष्ट हैं कि त्रुटि क्या फेंकनी चाहिए। यह हमारे परीक्षणों को स्पष्ट करता है और परीक्षण विफल होने पर निदान को आसान बनाता है।
नोट Should.ThrowAsync
अतुल्यकालिक विधि परीक्षण के लिए भी है ।
वी.एस. बिल्ट-इन यूनिट टेस्टिंग में यदि आप केवल यह सत्यापित करना चाहते हैं कि "कोई अपवाद" फेंका गया है, लेकिन आप प्रकार नहीं जानते हैं, तो आप एक कैच का उपयोग कर सकते हैं:
[TestMethod]
[ExpectedException(typeof(Exception), AllowDerivedTypes = true)]
public void ThrowExceptionTest()
{
//...
}
वैसे मैं बहुत ज्यादा योग करूँगा कि यहाँ बाकी सभी ने पहले क्या कहा ... वैसे भी, यहाँ कोड मैं अच्छे उत्तरों के अनुसार बनाया गया है :) सभी को करना बाकी है कॉपी और उपयोग ...
/// <summary>
/// Checks to make sure that the input delegate throws a exception of type TException.
/// </summary>
/// <typeparam name="TException">The type of exception expected.</typeparam>
/// <param name="methodToExecute">The method to execute to generate the exception.</param>
public static void AssertRaises<TException>(Action methodToExecute) where TException : System.Exception
{
try
{
methodToExecute();
}
catch (TException) {
return;
}
catch (System.Exception ex)
{
Assert.Fail("Expected exception of type " + typeof(TException) + " but type of " + ex.GetType() + " was thrown instead.");
}
Assert.Fail("Expected exception of type " + typeof(TException) + " but no exception was thrown.");
}
के बारे में उदाहरण के लिए nnnit डॉक्स देखें :
[ExpectedException( typeof( ArgumentException ) )]
यह इस बात पर निर्भर करने वाला है कि आप किस परीक्षण ढांचे का उपयोग कर रहे हैं?
उदाहरण के लिए, MbUnit में, आप यह सुनिश्चित करने के लिए एक विशेषता के साथ अपेक्षित अपवाद निर्दिष्ट कर सकते हैं कि आपको वह अपवाद मिल रहा है जिसकी आप वास्तव में अपेक्षा करते हैं।
[ExpectedException(typeof(ArgumentException))]
NUnit का उपयोग करने के मामले में , यह प्रयास करें:
Assert.That(() =>
{
Your_Method_To_Test();
}, Throws.TypeOf<Your_Specific_Exception>().With.Message.EqualTo("Your_Specific_Message"));
एनफ्लुएंट नामक एक बहुत बढ़िया पुस्तकालय है, जो आपके लेखन के तरीके को गति देता है और इसे आसान बनाता है ।
एक अपवाद को फेंकने के लिए एक जोरदार लिखना बहुत सरल है:
[Test]
public void given_when_then()
{
Check.ThatCode(() => MethodToTest())
.Throws<Exception>()
.WithMessage("Process has been failed");
}
हालांकि यह एक पुराना सवाल है, मैं चर्चा में एक नई सोच जोड़ना चाहूंगा। मैंने Expected, Arrange, Act, Assert होने के लिए Arrange, Act, Assert पैटर्न को बढ़ाया है। आप एक अपेक्षित अपवाद सूचक बना सकते हैं, फिर यह दावा करें कि इसे सौंपा गया था। यह आपके एस्कॉर्ट्स को कैच ब्लॉक में करने से ज्यादा साफ लगता है, अपने एक्ट सेक्शन को कोड की एक लाइन के लिए टेस्ट के तहत कॉल करने के लिए। आपको कोड में कई बिंदुओं से Assert.Fail();
या उसके पास नहीं है return
। फेंके गए किसी अन्य अपवाद के कारण परीक्षण विफल हो जाएगा, क्योंकि यह पकड़ा नहीं जाएगा, और यदि आपके अपेक्षित प्रकार के अपवाद को फेंक दिया जाता है, लेकिन यह वह नहीं था जिसकी आप उम्मीद कर रहे थे, संदेश या अन्य गुणों के खिलाफ जोर देना अपवाद मदद सुनिश्चित करें कि आपका परीक्षण अनजाने में पारित नहीं होगा।
[TestMethod]
public void Bar_InvalidDependency_ThrowsInvalidOperationException()
{
// Expectations
InvalidOperationException expectedException = null;
string expectedExceptionMessage = "Bar did something invalid.";
// Arrange
IDependency dependency = DependencyMocks.Create();
Foo foo = new Foo(dependency);
// Act
try
{
foo.Bar();
}
catch (InvalidOperationException ex)
{
expectedException = ex;
}
// Assert
Assert.IsNotNull(expectedException);
Assert.AreEqual(expectedExceptionMessage, expectedException.Message);
}