2015-10-20 16 views
5

Ho bisogno di avere un utente registrato per ciascuno dei miei test di unità, che mi costringe a fare una chiamata asincrona (il login) nel mio test SetUp.Setup test asincroni Unit in C#

Non riesco a trovare un modo per farlo funzionare, o ottengo eccezioni del puntatore nullo o firme non valide per l'installazione.

public async void SetUp() {} 

Questo rende tutta la mia prova non riuscire con i miei oggetti, probabilmente perché non sono collegato.

public async Task SetUp() {} 

fa tutta la mia prova ignorato perché la configurazione ha una firma non valida.

E mi piacerebbe non dover copiare le mie linee X di configurazione in ogni test, poiché sono tutte esattamente uguali e ... ecco a cosa serve l'installazione.

Cosa mi manca? questo sembra un problema banale.

Ecco quello che ho adesso, per il bene di che mostra qualcosa

CreateTicketViewModel _viewModel; 

     [SetUp()] 
     public async void SetUp() //I have tried using Task instead of void 
     { 

      IUserService userService = Dependency.Instance.Resolve<IUserService>(); 
      await userService.LoginAsync(this.UserName, this.Password); 

      _viewModel = Dependency.Instance.Resolve<CreateTicketViewModel>(); 
     } 

     [TearDown()] 
     public void TearDown() 
     { 
      _viewModel = null; // I have tried removing this 
     } 

     [Test()] 
     public void Initialization() 
     { 
      // If I put what's in SetUp here and add "async" before void, 
      // it works just fine 

      Assert.IsNotNull(_viewModel); 
      Assert.IsNotNull(_viewModel.Ticket); 
     } 
+0

Ho letto molti post sul blog che non hanno vuoto asincrono in SUT, che non ho, ma nessuno di questi post sul blog parla del test stesso. Ho un problema di progettazione? –

+0

Non è possibile rendere i metodi di test asincroni anziché il metodo di installazione? Oppure potresti persino rendere il metodo SetUp sincrono. L'ex è raccomandato però. –

+0

Un test asincrono con solo asserzioni in esso mostra un avvertimento. Spero di evitarlo, se possibile. –

risposta

4

A seconda del framework di unit test si utilizza async installazione non può essere gestita correttamente dal quadro.

nel caso NUnits, penso che non supporti ancora i metodi di installazione asincrona.

Che cosa si deve fare nel vostro programma di installazione è quello di aspettare solo in modo sincrono per il login per completare:

userService.LoginAsync(this.UserName, this.Password).Wait();

EDIT: Sembra che sia una questione aperta https://github.com/nunit/nunit/issues/60

E 'il caso per MSTests anche.

2

Potresti non solo rendere il vostro metodo di installazione non async a tutti e scrivere questo?

new Task(() => userService.LoginAsync(this.UserName, this.Password)).RunSynchronously() 
+0

Quando faccio questo, il contenuto del mio userService è ancora nullo all'avvio del test, e quindi fallisce. Si noti che ci sono più chiamate asincrone dietro quel metodo LoginAsync. –

+0

sebbene mi piaccia l'idea di eseguire l'accesso in modo sincrono, –

2

Le configurazioni Async non sono supportate ma sono supportati i metodi di test asincroni. È possibile rendere i metodi di test asincroni anziché il metodo di installazione.

[TestFixture] 
public class AsyncSetupTest 
{ 
    private Task<CreateTicketViewModel> viewModelTask; 

    [SetUp()] 
    public void SetUp() 
    { 
     viewModelTask = Task.Run(async() => 
     { 
      IUserService userService = Dependency.Instance.Resolve<IUserService>(); 
      await userService.LoginAsync(this.UserName, this.Password); 

      return Dependency.Instance.Resolve<CreateTicketViewModel>(); 
     }); 
    } 

    [Test()] 
    public async Task Initialization() 
    { 
     CreateTicketViewModel viewModel = await viewModelTask; 

     Assert.IsNotNull(viewModel); 
     Assert.IsNotNull(viewModel.Ticket); 
    } 
} 

Idea è, invece di ottenere tutto il lavoro di preparazione fatto in Setup metodo, creiamo un Task che rappresenta il completamento della messa a punto e in attesa che nel metodo Test.

In questo modo non si sta ripetendo tutta la logica di installazione. Ma basta estrarre il ViewModel da Task in tutti i metodi di prova.

+0

, ma ciò funzionerebbe, ma mi richiederebbe comunque di avere una singola linea ripetuta in ogni test; ma in effetti è già meglio di quello che ho fatto. Grazie. D'altra parte, la risposta di Dan Dinu fornisce una soluzione che funziona "così com'è" con la possibilità di avere solo i miei asserti nei miei test, il che implica avere meno codice e un blocco di codice più piccolo nella mia configurazione. –

+0

@ Zil Funzionerebbe. Ma il blocco del codice asincrono non è mai una buona idea. [Potresti ottenere un deadlock] (http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html). [Riferisciti anche a questo] (http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115163.aspx). –

+0

Accetto il codice di produzione, ma voglio che i miei test siano in attesa qui mentre il login è in corso. Pensi che sia così male in questo specifico scenario? Sapendo che non sto facendo altre chiamate asincrone qui (invece che all'interno del login stesso) –