In alternativa mediante l'attributo ExpectedException
, a volte mi definisco due metodi utili per le mie classi di test:
AssertThrowsException()
prende un delegato e afferma che getta l'eccezione prevista con il previsto m essaggio.
AssertDoesNotThrowException()
prende lo stesso delegato e afferma che non genera un'eccezione.
Questo abbinamento può essere molto utile quando si desidera verificare che venga generata un'eccezione in un caso, ma non nell'altro.
Il loro utilizzo il mio codice di prova di unità potrebbe essere simile a questo:
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);
bello e pulito eh?
mio AssertThrowsException()
e AssertDoesNotThrowException()
metodi sono definiti in una classe base comune come segue:
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);
}
}
Molti framework di test delle unità implementano errori di asserzione come eccezioni. Quindi Assert.Fail() nel secondo caso verrà catturato dal blocco catch (Exception), che nasconderà il messaggio di eccezione. È necessario aggiungere una presa (NUnit.Framework.AssertionException) {throw;} o simile - vedere la mia risposta. – GrahamS
@Graham - Ho scritto questo in cima alla mia testa. Ordinariamente vorrei anche stampare il messaggio di eccezione oltre al suo tipo. Il punto è che il test fallirebbe dato che il secondo handler avrebbe colto l'errore di asserzione e "refail" con informazioni sull'errore. – tvanfosson
Sebbene il codice sia funzionalmente valido, non è consigliabile utilizzare l'attributo ExpectedException (poiché è troppo vincolante e soggetto a errori) o scrivere un blocco try/catch in ogni test (poiché è troppo complicato e soggetto a errori). Utilizzare un metodo di asserzione ben progettato, fornito dal framework di test o scritto da soli. Puoi ottenere un codice migliore e non dovrai scegliere tra le diverse tecniche o passare da una all'altra mentre il test cambia. Vedi http://stackoverflow.com/a/25084462/2166177 – steve