2014-05-23 13 views
14

Abbiamo utilizzato xUnit Framework nel nostro progetto come framework di test sin dall'inizio. Attualmente ci sono più di 2200 test unitari nel progetto e tutto sembra a posto.xUnit Async Test non funziona correttamente

Ma ieri ho deciso di eseguire i test unitari alle build CI e alle build notturne. Combattere con il controller di team building per eseguire i test xunit per 1-2 ore riesco a eseguire i test. Ma c'è stato un problema, ci sono 22 avvisi riguardanti test come sotto, - Xunit.Sdk.EqualException: Assert.Equal() Fallimento o - System.ArgumentNullException: Il valore non può essere nullo.

Dopo un po 'di ricerche mi sono reso conto che questi test devono essere falliti ma sembrano passati perché tutti questi test sono contrassegnati con una parola chiave "async".

In realtà non ci dovrebbe essere alcun errore, perché xUnit supporta test asincroni per quanto riguarda questi messaggi http://bradwilson.typepad.com/blog/2012/01/xunit19.html http://sravi-kiran.blogspot.com.tr/2012/11/UnitTestingAsynchronousMethodsUsingMSTestAndXUnit.html Howerver realtà è più lieve differenza per me. Sì xUnit funziona senza problemi ma non esegue correttamente i test.

Ecco due piccoli metodi.

public async Task<string> AsyncTestMethod() { 
    throw new Exception("Test"); 
} 
public string NormalTestMethod() { 
    throw new Exception("Test"); 
} 

Come si può vedere unica differenza, il primo metodo definito "asincrono" E qui ci sono due test per questi metodi.

[Fact] 
    public async void XunitTestMethod_Async() { 
     Program p = new Program(); 
     string result = await p.AsyncTestMethod(); 
     Assert.Equal("Ok", result); 
    } 
     [Fact] 
    public void XunitTestMethod_Normal() { 
     Program p = new Program(); 
     string result = p.NormalTestMethod(); 
     Assert.Equal("Ok", result); 
    } 

Entrambi i metodi originali tiri eccezione, quindi penso che entrambi i test dovesse fallire, ma il risultato è diverso. È possibile visualizzare i risultati: Test results

XunitTestMethod_Async test pass ma XunitTestMethod_Normal ha esito negativo. Non è il caso di lanciare un'eccezione, è possibile modificare il contenuto del metodo qualunque cosa vogliate che AsyncTestMethod passi sempre.

ecco la soluzione esempio: https://github.com/bahadirarslan/AsyncTestWithxUnit

potrei frainteso o pensare sbagliato, ma ora questo comportamento provoca un sacco di dolore per me

Spero che mi può illuminare.

PS: ho creato un problema nella pagina xUnit github, ma non potevo essere sicuro che ciò sia causato da me o xUnit. Quindi ho deciso di chiedere anche a me. Problema: https://github.com/xunit/xunit/issues/96

+2

Provare a cambiare la firma 'async void' in' async Task' per 'XunitTestMethod_Async'. Ricordo di aver visto una domanda simile a cui avevo chiesto e risposto prima, ma che non riesco a trovarla. – Noseratio

+2

@Noseratio incredibile. Non potevo pensare che la risposta sia semplice come questa. Se pubblichi la tua risposta ai commenti, vorrei accettarla. Grazie mille. –

risposta

27

Il problema è che async void metodo non restituisce un oggetto che Task xUnit potrebbe esaminare per le eccezioni. xUnit non può nemmeno tracciare il completamento di un particolare metodo async void, al contrario di un metodo async Task.

Inoltre, i metodi non generano eccezioni sullo stesso frame di stack, anche per le eccezioni generate dalla parte sincrona del metodo. Piuttosto, le eccezioni vengono propagate al contesto di sincronizzazione corrente tramite SynchronizationContext.Post (nel caso SynchronizationContext.Current != null) o in altro modo tramite ThreadPool.QueueUserWorkItem. Questo comportamento è diverso dai metodi async Task, more details. È possibile tenere traccia del numero totale dei metodi async void in sospeso (tramite SynchronizationContext.OperationStarted/OperationCompleted), ma non dei singoli metodi.

Pertanto, è necessario risolvere la firma del metodo a async Task tramite la firma del metodo XunitTestMethod_Async.

+1

Molto interessante e una strana stranezza sul "vuoto asincrono", ma ha sicuramente un senso. Mi sono imbattuto casualmente in questa domanda, ma sono contento di averlo letto. –