2014-07-18 15 views
5

Sono sorpreso il mio punto di interruzione dopo await ing un metodo async che si trova su una linea che fa riferimento alla atteso Task<T> è mai colpito:Come utilizzare un punto di interruzione dopo l'attesa nel test dell'unità?

[Test] 
    public async void GetSomethingTest() 
    { 
     var service = SimpleIoc.Default.GetInstance<IService>(); 
     var result = await service.TryGetSomethingAsync(20); 
     Assert.IsTrue(result.IsSuccess); 
     Assert.IsNotNull(result.ReturnValue); 
    } 

Mettere un punto di interruzione sulla prima riga Assert non è mai colpito, ma il test viene superato.

Come interrompere in attesa di resi?

UPDATE: Credo che sia perché il quadro di prova non è await ing l'invocazione del metodo di prova, io sto usando NUnit 2.6.3 e che pretende async supporto, tuttavia se ciò che comporta la rottura dopo un await come ho Sto cercando di fare, non sono sicuro ...

+1

Modificare il metodo di test da vuoto asincrono a async Attività – Neel

+0

@Neel che non ha aiutato :( – markmnl

+1

Ho avuto tutti i tipi di problemi con i test delle unità di debug. Se non funziona nel modo desiderato, copiare il test a una ConsoleApplication e esegui il debug in questi casi.Pochi meno problemi. – nvoigt

risposta

10

Il problema è che il tuo metodo è async void. Questo ha una semantica ignifuga.

Concettualmente ciò che il metodo sta facendo con il async - utilizzo await assomiglia a questo:

[Test] 
public void GetSomethingTest() 
{ 
    var service = SimpleIoc.Default.GetInstance<IService>(); 
    service.TryGetSomethingAsync(20).ContinueWith(t => 
    { 
     var result = t.Result; 
     Assert.IsTrue(result.IsSuccess); 
     Assert.IsNotNull(result.ReturnValue); 
    }); 
} 

Ora dovrebbe essere chiaro quale sia il problema. Il metodo di prova torna immediatamente non appena TryGetSomethingAsync restituisce il valore Task. Quindi il test termina immediatamente. Poiché non sono state lanciate eccezioni, è un successo.

Se il framework di test supporta Task test -returning, è possibile correggere il test di fare ciò che si vuole semplicemente cambiando il tipo restituito alla Task invece di void.

[Test] 
public async Task GetSomethingTest() 
{ 
    var service = SimpleIoc.Default.GetInstance<IService>(); 
    var result = await service.TryGetSomethingAsync(20); 
    Assert.IsTrue(result.IsSuccess); 
    Assert.IsNotNull(result.ReturnValue); 
} 

Questo concettualmente tradurrà quanto segue.

[Test] 
public Task GetSomethingTest() 
{ 
    var service = SimpleIoc.Default.GetInstance<IService>(); 
    return service.TryGetSomethingAsync(20).ContinueWith(t => 
    { 
     var result = t.Result; 
     Assert.IsTrue(result.IsSuccess); 
     Assert.IsNotNull(result.ReturnValue); 
    }); 
} 

Notate come la continuazione Task viene restituito, in modo che il quadro test può ora attendere su di esso, assicurando che tutto il codice del test ha il tempo di correre prima che il test è considerato finito.

(tecnicamente un quadro potrebbe essere fatto funzionare nel caso async void pure, ma non so di alcuna ragione per cui sarebbe una buona caratteristica, quindi mi aspetto la maggior parte non gestirlo.)

Se il framework di test non supporta i test di ritorno attività, è possibile correggere il test utilizzando .Result anziché await.

[Test] 
public void GetSomethingTest() 
{ 
    var service = SimpleIoc.Default.GetInstance<IService>(); 
    var result = service.TryGetSomethingAsync(20).Result; 
    Assert.IsTrue(result.IsSuccess); 
    Assert.IsNotNull(result.ReturnValue); 
} 

Ciò semplicemente bloccare il thread corrente fino al Task restituito da TryGetSomethingAsync è completato.

+0

Passare a MSTest e tornare 'Task' ha risolto il mio problema, ma grazie alla risposta dettagliata, sono sicuro che aiuterà gli altri! – markmnl