2013-12-10 15 views
6

ho bisogno di scrivere uno unit test per la funzione successiva e ho visto che posso usare [ExpectedException]ExpectedException Assert

questa è la funzione da testare.

public static T FailIfEnumIsNotDefined<T>(this T enumValue, string message = null) 
     where T:struct 
    { 
     var enumType = typeof (T); 

     if (!enumType.IsEnum) 
     { 
      throw new ArgumentOutOfRangeException(string.Format("Type {0} is not an Enum, therefore it cannot be checked if it is Defined not have defined.", enumType.FullName)); 
     } 
     else if (!Enum.IsDefined(enumType, enumValue)) 
     { 
      throw new ArgumentOutOfRangeException(string.Format("{1} Value {0} is not does not have defined value in Enum of type {0}. It should not be...", enumType.FullName, message ?? "")); 
     } 

     return enumValue; 
    } 

e qui sarebbe andato il codice per testare le eccezioni che dovrebbero essere gettato

[TestMethod] 
    [ExpectedException(ArgumentOutOfRangeException(ArgumentException), "message")] 
    public void FailIfEnumIsNotDefined_Check_That_The_Value_Is_Not_Enum() 
    { 
     // PREPARE 
     // EXECUTE 
     // ASSERT 
    } 

Non ho idea deve fare l'asserzione per le eccezioni sia.

+1

Utilizzare 'Assert.Throws()' invece di 'ExpectedException', in quanto questo attributo supera il test se l'esc eption si è verificato in qualsiasi parte del codice del metodo di test. 'Assert.Throws' consente di verificare la posizione esatta del codice in cui si verifica l'eccezione. – sthotakura

+0

@sthotakura MSTest non ha Assert.Throws a meno che non si scriva uno personalizzato, il che è comunque la gestione dell'eccezione MSTest preferita. Simile a NUnit :) C'è un collegamento nella mia risposta – Spock

+0

@Spock Non lo sapevo, grazie! – sthotakura

risposta

17

ExpectedException solo afferma che eccezione del tipo specificato saranno gettati dal metodo di prova:

[TestMethod] 
[ExpectedException(typeof(ArgumentOutOfRangeException))] 
public void FailIfEnumIsNotDefined_Check_That_The_Value_Is_Not_Enum() 
{ 
    // PREPARE 
    // EXECUTE 
    // NO ASSERT!! 
} 

Se si vuole far valere altri parametri d'eccezione, quindi si dovrebbe utilizzare try..catch nel vostro metodo di prova:

[TestMethod]  
public void FailIfEnumIsNotDefined_Check_That_The_Value_Is_Not_Enum() 
{ 
    // PREPARE 

    try 
    { 
     // EXECUTE 
     Assert.Fail() 
    } 
    catch(Exception exception) 
    {   
     // ASSERT EXCEPTION DETAILS 
    } 
} 

È possibile scrivere il proprio metodo per far valere l'eccezione è stato lanciato per evitare di ripetere lo stesso codice di prova più e più volte:

public TException AssertCatch<TException>(Action action) 
    where TException : Exception 
{ 
    try 
    { 
     action(); 
    } 
    catch (TException exception) 
    { 
     return exception; 
    } 

    throw new AssertFailedException("Expected exception of type " + 
            typeof(TException) + " was not thrown"); 
} 

Usage:

var exception = AssertCatch<ArgumentOutOfRangeException>(() => /* EXECUTE */); 
Assert.AreEqual("foo", exception.Message); 
2

È necessario utilizzare ExpectedException in modo diverso:

[TestMethod] 
[ExpectedException(typeof(ArgumentOutOfRangeException))] 
public void MyTestSomething() 

e quindi codificare il test in modo che l'eccezione prevista si butta.

0

Non hai bisogno di un'affermazione se stai usando l'attributo ExpectedException, infatti il ​​tuo codice non dovrebbe essere in grado di arrivare all'asserzione.

aspetto: http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.expectedexceptionattribute.aspx

Se si vuole essere sicuri viene generata l'eccezione si dovrebbe mettere un Assert.Fail() dopo l'operazione che dovrebbe generare l'eccezione, in questo caso, se l'eccezione non viene lanciata, il test fallirà.

1

Probabilmente si desidera cercare più personalizzazione delle eccezioni. MSTest ExpectedException attr ha diversi difetti. Prova ad usare l'approccio this, che ti dà un controllo preciso sull'eccezione generata.

1

affermare l'eccezione è gettare con il messaggio di eccezione corretta con:

var ex = Assert.Throws<Exception>(() => _foo.DoSomething(a, b, c)); 
Assert.That(ex.Message, Is.EqualTo("Your exception message")); 
1

Mentre ExpectedException non può essere utilizzato come-è quello di verificare il messaggio del eccezione, è possibile implementare la propria logica di validazione eccezione ereditando da ExpectedExceptionBaseAttribute:

Implementando la propria verifica delle eccezioni previste.è possibile specificare ulteriori informazioni e requisiti che il built-in metodi della classe ExpectedExceptionAttribute non può gestire, come ad esempio il seguente:

  • Verifica dello stato di eccezione.
  • In attesa di più di un tipo di eccezione.
  • Visualizzazione di un messaggio personalizzato quando viene emesso un tipo di eccezione errato.
  • Controllo dell'esito di un test negativo.

Nel tuo caso, potrebbe essere simile a questa:

public sealed class ExpectedExceptionMessageAttribute<T> : ExpectedExceptionBaseAttribute 
{ 
    readonly string _expectedMessage; 
    public ExpectedExceptionMessageAttribute(string expectedMessage) 
    { 
     _expectedMessage = expectedMessage; 
    } 

    protected override void Verify(System.Exception exception) 
    { 
     // Handle assertion exceptions from assertion failures in the test method 
     base.RethrowIfAssertException(exception); 

     Assert.IsInstanceOfType(exception, typeof(T), "wrong exception type"); 
     Assert.AreEqual(_expectedMessage, exception.Message, "wrong exception message"); 
    } 
} 

Detto questo, vorrei ancora propenso a utilizzare la diretta try - approccio catch anche se, come è più specifico in dove esattamente si prevede che l'eccezione sia lanciata:

public static void Throws<T>(Action action, Predicate<T> predicate = null) 
        where T : Exception 
{ 
    try 
    { 
     action(); 
    } 
    catch (T e) 
    { 
     if (predicate == null || predicate(e)) 
     { 
      return; 
     } 

     Assert.Fail($"Exception of type {typeof(T)} thrown as expected, but the provided predicate rejected it: {e}"); 
    } 
    catch (Exception e) 
    { 
     Assert.Fail($"Expected exception of type {typeof(T)} but a different exception was thrown: {e}"); 
    } 

    Assert.Fail($"No exception thrown, expected {typeof(T)}"); 
}