2013-03-26 17 views
5

Non so da dove cominciare, ma lascia che ti dia una breve idea su dove sono e cosa voglio raggiungere. Sono abbastanza nuovo per Unit Testing su MVVM e ho difficoltà a testare i comandi che ho esposto usando le proprietà dei comandi delegate PRISM. I miei comandi delegati chiamano il metodo asincrono che deve essere aspettato così posso ottenere il risultato effettivo. Di seguito è riportato un metodo asyc che viene chiamato dal metodo che volevo testare.Come testare un ViewModel con metodo asincrono.

async void GetTasksAsync() 
     { 
      this.SimpleTasks.Clear(); 
      Func<IList<ISimpleTask>> taskAction =() => 
       { 
        var result = this.dataService.GetTasks(); 
        if (token.IsCancellationRequested) 
         return null; 
        return result; 
       }; 
      IsBusyTreeView = true; 

      Task<IList<ISimpleTask>> getTasksTask = Task<IList<ISimpleTask>>.Factory.StartNew(taskAction, token); 
      var l = await getTasksTask;   // waits for getTasksTask 


      if (l != null) 
      { 
       foreach (ISimpleTask t in l) 
       { 
        this.SimpleTasks.Add(t); // adds to ViewModel.SimpleTask 
       } 
      } 
     } 

anche qui è il comando nel mio VM che chiama il metodo asincrono sopra

this.GetTasksCommand = new DelegateCommand(this.GetTasks); 
     void GetTasks() 
     { 
       GetTasksAsync(); 
     } 

e ora il mio metodo di prova va come

[TestMethod] 
     public void Command_Test_GetTasksCommand() 
     { 
      MyViewModel.GetTaskCommand.Execute(); // this should populate ViewModel.SimpleTask 
      Assert.IsTrue(MyBiewModel.SimpleTask != null) 
     } 

Attualmente quello che sto ottenendo è che la mia ViewModel.SimpleTask = null questo perché non attende il completamento del metodo async. Capisco che ci siano alcuni argomenti correlati a questo già in overflow dello stack, ma non sono riuscito a trovare qualcosa relativo ai miei DelegateCommands.

risposta

9

Il metodo GetTasksAsync deve restituire un'attività in modo che si possa effettivamente attendere.

Raccomando this series su Channel9 uno this episode appositamente per spiegare il tuo problema.

Giusto per fare è chiaro: semplicemente cambiando la firma del GetTasksAsync per

Task GetTasksAsync(); 

ti permette di fare questo:

var t = GetAsync(); 
t.Wait(); 
Assert(...); 

Nel caso in cui davvero si vuole testare il comando nel test di unità e non il metodo effettivamente chiamato dal comando puoi usare un campo nel ViewModel per memorizzare l'attività in attesa (non così pulita) o sostituire il tuo DelegateCommand con qualcosa come descritto in questo post: Awaitable DelegateCommand

Aggiornamento: oltre al post sul blog e considerando che stai usando PRISM, dovresti dare un'occhiata a Project Kona dalla stessa squadra di PRISM. Hanno effettivamente implementato DelegateCommand to support AsyncHandlers

+3

O meglio, questo consente di utilizzare un test di unità 'async Task' e di attendere' GetTasksAsync() '. –

+0

Grazie per la risposta.Tuttavia, questo GetTasksAsync() è un metodo privato all'interno del mio Viewmodel e non vuole esporre a nessun altro oggetto all'interno del mio progetto e viene chiamato solo dai delegati. Detto questo, sto solo testando i metodi pubblici. Questi delegati sono esposti come pubblici. L'introduzione di un altro campo potrebbe essere un modo per andare, ma hai ragione sarà sporco. Vedrò il link Ammitable Delegate COmmand che mi hai mandato e vedere se sarà utile. Aggiornamento –

+0

: ho implementato la risposta sopra riportata per il fatto che non potevo ancora allenare altri sostituti della soluzione, ad es. Awaitable DelegateCommand. Implementare questo significa che ho cambiato i miei metodi privati ​​in pubblico (questo odore!), Ora il mio problema è che quando si chiama GetTaskAsync() usando t.Wait() questo lancia InnerException = {"Questo tipo di CollectionView non supporta le modifiche ai suoi SourceCollection da un thread diverso dal thread Dispatcher. "}. Questo perché aggiunge elementi alla mia raccolta dall'altro thread. Qualche idea? –

Problemi correlati