Kaip naudoti „Assert“, kad patikrintumėte, ar pasirinkta išimtis?

Kaip naudoti „Assert“ (ar kitą bandymų klasę?) Norėdami įsitikinti, kad pasirinkta išimtis?

705
01 июня '09 в 8:01 2009-06-01 08:01 Alex yra nustatytas birželio 01'09, 08:01 2009-06-01 08:01
@ 22 atsakymai

„Visual Team Team Test“ atveju, bandymo metodui taikote „ExpectedException“ atributą.

Dokumentų pavyzdys yra čia: įrenginio bandymas naudojant bandymus naudojant „Visual Studio“ testą.

 [TestMethod] [ExpectedException(typeof(ArgumentException), "A userId of null was inappropriately allowed.")] public void NullUserIdInConstructor() { LogonInfo logonInfo = new LogonInfo(null, "P@ss0word"); } 
843
01 июня '09 в 8:09 2009-06-01 08:09 atsakymą pateikė Kevin Pullin, birželio 1 d., 08:09, 2009-06-01 08:09

Paprastai jūsų bandymų aplinka bus atsakymas. Bet jei ji nėra pakankamai lanksti, visada galite tai padaryti:

 try { somethingThatShouldThrowAnException(); Assert.Fail(); // If it gets to this line, no exception was thrown } catch (GoodException) { } 

Kaip nurodo @Jonas, tai NEGALIMA atlikti pagrindinį sugavimą.

 try { somethingThatShouldThrowAnException(); Assert.Fail(); // raises AssertionException } catch (Exception) { // Catches the assertion exception, and the test passes } 

Jei tikrai turite sugauti išimtį, turite perkelti Assert.Fail (). Tačiau iš tikrųjų tai yra ženklas, kad neturėtumėte rašyti rankomis; patikrinkite savo bandymų struktūrą ir patikrinkite, ar galite naudoti prasmingesnę išimtį bandymui.

 catch (AssertionException) { throw; } 

Turėtumėte sugebėti pritaikyti šį požiūrį į tai, kas jums patinka - nurodant, kokios išimtys taikomos sužvejotų žuvų kiekiui. Jei tikitės tik tam tikrų tipų, catch fiksavimo užraktą:

 } catch (GoodException) { } catch (Exception) { // not the right kind of exception Assert.Fail(); } 
228
01 июня '09 в 8:06 2009-06-01 08:06 atsakymą pateikė ojrac birželio 1 d. 09: 08:06 2009-06-01 08:06

Mano pageidaujamas metodas, kaip tai įgyvendinti, yra rašyti metodą, vadinamą Throws, ir naudoti jį kaip ir bet kurį kitą Assert metodą. Deja, .NET neleidžia rašyti statinio pratęsimo metodo, todėl negalite naudoti šio metodo taip, lyg jis tikrai priklausytų Asertų klasės susirinkimui; tiesiog paskambinkite į „MyAssert“ arba kažką panašaus. Klasė atrodo taip:

 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)) ); } } } } 

Tai reiškia, kad jūsų vieneto testas atrodo taip:

 [TestMethod()] public void ExceptionTest() { String testStr = null; MyAssert.Throws<NullReferenceException>(() => testStr.ToUpper()); } 

Kas atrodo ir elgiasi daug daugiau nei kiti vieneto testo sintaksės.

100
12 апр. Richiban atsakymas, pateiktas balandžio 12 d 2011-04-12 14:20 '11, 14:20, 2011-04-12 14:20

Jei naudojate MSTest, kuris iš pradžių neturėjo „ ExpectedException atributo, galite tai padaryti:

 try { SomeExceptionThrowingMethod() Assert.Fail("no exception thrown"); } catch (Exception ex) { Assert.IsTrue(ex is SpecificExceptionType); } 
59
01 июня '09 в 8:10 2009-06-01 08:10 atsakymą davė Jon Limjap, birželio 1 d., 09:10, 2009-06-01 08:10

jei naudojate NUNIT, galite tai padaryti:

 Assert.Throws<ExpectedException>(() => methodToTest()); 


Taip pat galite išsaugoti išskirtą išimtį, kad patikrintumėte toliau:

 ExpectedException ex = Assert.Throws<ExpectedException>(() => methodToTest()); Assert.AreEqual( "Expected message text.", ex.Message ); Assert.AreEqual( 5, ex.SomeNumber); 

Žr. Http://nunit.org/docs/2.5/exceptionAsserts.html

43
04 дек. atsakymas duotas damir 04 dec. 2013-12-04 14:02 '13, 14:02 2013-12-04 14:02

Būkite atsargūs naudodami „ExpectedException“, nes tai gali sukelti keletą spąstų, kaip parodyta čia:

http://geekswithblogs.net/sdorman/archive/2009/01/17/unit-testing-and-expected-exceptions.aspx

Ir čia:

http://xunit.github.io/docs/comparisons.html

Jei reikia išbandyti išimtis, jie nesutaria mažiau. Galite naudoti bandymo {act / fail} sugavimo {assert} metodą, kuris gali būti naudingas sistemoms, neturinčioms tiesioginės paramos išimties testams, išskyrus „ExpectedException“.

Geriausia alternatyva yra naudoti „xUnit.NET“, kuri yra labai moderni, į ateitį orientuota ir išplėsta modulinė testavimo sistema, išmokusi iš visų kitų klaidų ir patobulinta. Vienas iš tokių patobulinimų yra „Assert.Throws“, kuris suteikia daug geresnę sintaksę išimčių patvirtinimui.

XUnit.NET galite rasti „github“: http://xunit.github.io/

35
01 июня '09 в 8:22 2009-06-01 08:22 atsakymas duotas jrista 01 birželio '09, 08:22 2009-06-01 08:22

Projekte, kuriame dirbau, yra dar vienas sprendimas.

Iš pradžių man nepatinka „ExpectedExceptionAttribute“, nes jame atsižvelgiama į tai, kuris metodas paskambino dėl išimties.

Aš tai padarysiu naudodamasis pagalbos pagalba.

Bandymas

 [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; } 

Švelnus, ar ne?)

24
02 окт. atsakymą pateikė Glenn 02 okt. 2010-10-02 00:13 '10 ne 0:13 2010-10-02 00:13

Tai yra bandymo metodo atributas ... nenaudojate Assert. Tai atrodo taip:

 [ExpectedException(typeof(ExceptionType))] public void YourMethod_should_throw_exception() 
15
01 июня '09 в 8:09 2009-06-01 08:09 atsakymas yra pateikiamas nario 01 birželio 09 d. 8:09 2009-06-01 08:09

Galite atsisiųsti paketą iš „Nuget“ naudojant: PM> „Install-Package“ „MSTestExtensions“ , kuris prideda „Assert.Throws“ () sintaksę „nTnit / xUnit“ stiliui „MsTest“.

Aukšto lygio nurodymai: įdėkite surinkimą ir paveldėkite iš „BaseTest“ ir galite naudoti sintaksę „Assert.Throws“ ().

Pagrindinis metimo metimo metodas yra toks:

 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))); } } 

Atskleidimas: parengiau šį paketą.

Daugiau informacijos: http://www.bradoncode.com/blog/2012/01/asserting-exceptions-in-mstest-with.html

13
08 апр. Atsakymą pateikė Bradley Braithwaite, balandžio 8 d. 2015-04-08 02:11 '15, 2:11 am 2015-04-08 02:11

„MSTest“ (v2) dabar turi „Assert.ThrowsException“ funkciją, kuri gali būti naudojama taip:

 Assert.ThrowsException<System.FormatException>(() => { Story actual = PersonalSite.Services.Content.ExtractHeader(String.Empty); }); 

Ją galite įdiegti naudodami „nuget“: Install-Package MSTest.TestFramework

11
18 окт. Martin Beeby atsakymas, pateiktas spalio 18 d 2016-10-18 19:03 '16 at 19:03 PM 2016-10-18 19:03

Nerekomenduojame naudoti atributo ExpectedException (nes jis yra pernelyg ribotas ir klaidingas) arba kiekviename bandyme parašykite bandomąjį / sugavimo bloką (nes jis yra per daug sudėtingas ir klaidingas). Naudokite gerai apgalvotą metodą, kurį pateikia jūsų bandymų infrastruktūra, arba parašykite savo. Štai ką parašiau ir naudoju.

 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)); } } 

Naudojimo pavyzdys:

  [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) } 

PASTABOS

Išimties grąžinimas vietoj patvirtinimo patvirtinimo yra pagrįsta idėja, išskyrus tai, kad šio pareiškimo skambučio sintaksė labai skiriasi nuo kitų naudojamų teiginių.

Skirtingai nuo kitų, aš naudoju „paskirstymą“ vietoj „metimų“, nes galime tik patikrinti, ar išimtis yra skleidžiama iš skambučio. Negalime tiesiogiai patikrinti, ar pasirinkta išimtis. Bet manau, kad galėtumėte pavaizduoti metimus, nurodydami: išmestus ir ne sugautus.

GALUTINIS ATSIŽVELGIMAS

Prieš pereinant prie šio požiūrio, naudoju atributą „ExpectedException“, kai testas patikrino tik išimties tipą ir naudojo bandomąjį / sugavimo bloką, jei reikia papildomo patikrinimo. Tačiau ne tik turėjau galvoti apie tai, kokį metodą naudoti kiekvienam testui, bet kodo keitimą iš vieno metodo į kitą, nes pasikeitė poreikiai, nebuvo triviška pastanga. Naudojant vieną nuoseklų metodą sutaupoma protinių pastangų.

Taigi šis požiūris yra sportiškas: naudojimo paprastumas, lankstumas ir patikimumas (sunku tai padaryti neteisingai).

5
01 авг. atsakymas duotas steve 01 rug. 2014-08-01 19:14 '14, 19:14, 2014-08-01 19:14

Tai galite pasiekti naudodami vieną eilutę.

Jei jūsų foo.bar() operacija yra asinchroninė:

 await Assert.ThrowsExceptionAsync<Exception>(() => foo.bar()); 

Jei foo.bar() nėra asinchroninis

 Assert.ThrowsException<Exception>(() => foo.bar()); 
4
01 нояб. Atsakymas pateikiamas Cfrim lapkričio 1 d. 2018-11-01 13:38 '18, 13:38 pm 2018-11-01 13:38

„@Richiban“ teikiamas pagalbininkas veikia gerai, išskyrus tai, kad jis nesprendžia situacijos, kai išimtis iškeliama, tačiau tipas nėra tikėtinas. Šie adresai:

 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)) ); } } } } 
4
05 апр. Martin Connell atsakymas 05 Bal 2013-04-05 03:02 '13, 3:02 2013-04-05 03:02

Kadangi paminėtumėte kitų bandymų klasių naudojimą, geresnis pasirinkimas nei „ ExpectedException atributas yra naudoti „ Shoudly should.Throw“ .

 Should.Throw<DivideByZeroException>(() => { MyDivideMethod(1, 0); }); 

Tarkime, mes turime reikalavimą, kad klientas turi adresą, kad būtų galima sukurti užsakymą. Jei ne, „ CreateOrderForCustomer metodas turėtų CreateOrderForCustomer ArgumentException . Tada galėtume rašyti:

 [TestMethod] public void NullUserIdInConstructor() { var customer = new Customer(name := "Justin", address := null}; Should.Throw<ArgumentException>(() => { var order = CreateOrderForCustomer(customer) }); } 

Tai geriau nei naudojant „ ExpectedException atributą, nes kalbame konkrečiai apie tai, kas turėtų sukelti klaidą. Dėl to mūsų bandymų reikalavimai tampa aiškesni, taip pat palengvina diagnostiką, jei bandymai yra nesėkmingi.

Pastaba Asinchroniniam bandymo metodui taip pat yra „ Should.ThrowAsync .

3
05 февр. Atsakymą pateikė Justin J Stark 05 vasaris. 2016-02-05 21:07 '16 at 21:07 2016-02-05 21:07

Na, aš gana daug apibendrinu tai, ką visi kiti čia sakė ... Bet kuriuo atveju, čia yra kodas, kurį sukūriau pagal gerus atsakymus :) Viskas, ką jums reikia padaryti, tai kopijuoti ir naudoti ...

 /// <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."); } 
3
14 сент. Atsakymas suteikiamas 14 sėklų . 2012-09-14 23:12 '12 23:12 2012-09-14 23:12

Arba galite pabandyti patikrinti, ar išimtys yra neįtrauktos dėl dviejų bandymų eilučių.

 var testDelegate = () => MyService.Method(params); Assert.Throws<Exception>(testDelegate); 
3
14 дек. Atsakymą pateikė Matias gruodžio 14 d. 2016-12-14 15:17 '16 at 15:17 2016-12-14 15:17

Jei naudojate NUnit , pabandykite:

 Assert.That(() => { Your_Method_To_Test(); }, Throws.TypeOf<Your_Specific_Exception>().With.Message.EqualTo("Your_Specific_Message")); 
2
05 мая '17 в 8:39 2017-05-05 08:39 Atsakymą pateikė Amir Chatrbahr 05 Gegužės 17 d., 8:39 2017-05-05 08:39

VS įmontuotame vieneto bandyme, jei norite tik patikrinti, ar pasirinkta „bet kokia išimtis“, bet nežinote, kokio tipo, galite naudoti „catch all“:

 [TestMethod] [ExpectedException(typeof(Exception), AllowDerivedTypes = true)] public void ThrowExceptionTest() { //... } 
2
27 июня '17 в 1:50 2017-06-27 01:50 atsakymą pateikė TTT birželio 27 d. 17 val. 1:50 2017-06-27 01:50

Peržiūrėkite pavyzdžius apie „ NUnit“ dokumentus :

 [ExpectedException( typeof( ArgumentException ) )] 
2
01 июня '09 в 8:10 2009-06-01 08:10 atsakymą davė Jon Masters, birželio 1 d., 09:10, 2009-06-01 08:10

Tai priklauso nuo to, kurią bandymų aplinką naudojate?

Pvz., „MbUnit“ galite nurodyti tikėtiną išimtį su atributu, kad įsitikintumėte, jog gaunate išimtį, kurią tikrai tikitės.

 [ExpectedException(typeof(ArgumentException))] 
2
01 июня '09 в 8:09 2009-06-01 08:09 atsakymą pateikė jay nuo birželio 01'09 iki 08:09 2009-06-01 08:09

Net jei tai yra senas klausimas, norėčiau įtraukti naują diskusiją. Pratęsiau „Arrange, Act“, „Assert“ šabloną, kuris turėtų būti tikimasi, supaprastintas, veiktas, patvirtintas. Galite padaryti tikėtiną išimties rodyklę ir tada pareikšti, kad jis buvo priskirtas. Tai atrodo švaresni nei jūsų pareiškimų vykdymas sugavimo bloke, palikdami savo įstatymo skyrių daugiausia tik vienai kodo eilutei, kad paskambintumėte bandomą metodą. Taip pat neturėtumėte turėti Assert.Fail(); arba return iš kelių kodo taškų. Bet kuri kita išimtis, kuri bus išmesta, sukels bandymą nepavykti, nes ji nebus sugauta, ir jei iš jūsų numatyto tipo bus pasirinkta išimtis, tačiau tai nėra ta, kurią tikėjotės, pranešimas prieš pranešimą ar kitas išimties savybes užtikrina, kad bandymas nepavyktų netyčia.

 [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); } 
1
11 сент. Atsakymą pateikė Adam Venezia rugsėjo 11 d. 2015-09-11 22:56 '15 , 10:56 pm 2015-09-11 22:56

Yra siaubinga biblioteka, vadinama NFluent, kuri pagreitina ir palengvina jūsų pareiškimų rašymo būdą.

Tai gana paprasta parašyti pareiškimą, kad būtų išleista išimtis:

  [Test] public void given_when_then() { Check.ThatCode(() => MethodToTest()) .Throws<Exception>() .WithMessage("Process has been failed"); } 
0
21 янв. atsakymas pateikiamas mirind4 Jan 21 2019-01-21 14:39 '19, 14:39 pm 2019-01-21 14:39