2016-05-19 13 views
0

Ich habe ein XF-Projekt, das Mvvm Light und Ninject verwendet. Ich versuche, Einheitentests für meine Viewmodels zurückzuverfolgen und zu schreiben, aber ich laufe immer wieder auf Probleme, wo Xamarin.Forms.Init() aufgerufen werden muss oder ich habe Referenzen auf Device.BeginInvokeOnMainThread oder andere UI-spezifische Sachen in RelayCommands.Wie organisiert man Code in Xamarin Forms ViewModel für Komponententests?

So ein typisches RelayCommand könnte wie folgt aussehen:

public RelayCommand DeleteGameCommand 
{ 
    get 
    { 
     return _deleteGameCommand 
      ?? (_deleteGameCommand = new RelayCommand(
      async() => 
      { 
       Device.BeginInvokeOnMainThread(() => ToggleMasterMenuDisplayCommand.Execute(null)); 
       var response = await 
        ((MasterDetailPage) Application.Current.MainPage).Detail.DisplayActionSheet("Are you sure?", "Cancel", 
         "Delete Game"); 
       if (response == "Delete Game") 
       { 
        StopTimer(); 

        using (new Busy(this, "Deleting Game...")) 
        { 
         await GameService.DeleteGame(Game, true); 
         await AzureService.SyncGameInfoForGame(Game.GameId, true); 
        } 

        App.Current.Container.Get<DashboardViewModel>().ShouldRefreshDataOnNextDisplay(); 
        Device.BeginInvokeOnMainThread(() => 
        { 
         App.Current.HideLoading(); 
         LoadHomeAsMainPage(); 
        }); 
       } 
      })); 
    } 
} 

Busy() ruft einige UI Sachen Fortschrittsindikatoren angezeigt werden soll. App.Current.Container ist mein Ninject-Kernel.

Soll ich dies wie etwas mehr zu suchen Refactoring:

public RelayCommand DeleteGameCommand 
{ 
    get 
    { 
     return _deleteGameCommand 
      ?? (_deleteGameCommand = new RelayCommand(
      async() => 
      { 
       Device.BeginInvokeOnMainThread(() => ToggleMasterMenuDisplayCommand.Execute(null)); 
       var response = await 
        ((MasterDetailPage) Application.Current.MainPage).Detail.DisplayActionSheet("Are you sure?", "Cancel", 
         "Delete Game"); 
       if (response == "Delete Game") 
       { 
        StopTimer(); 

        using (new Busy(this, "Deleting Game...")) 
        { 
         await BusinessLogic.DeleteGame(Game,true); 
        } 

        App.Current.Container.Get<DashboardViewModel>().ShouldRefreshDataOnNextDisplay(); 
        Device.BeginInvokeOnMainThread(() => 
        { 
         App.Current.HideLoading(); 
         LoadHomeAsMainPage(); 
        }); 
       } 
      })); 
    } 
} 



public class BusinessLogic 
{ 
    public async Task DeleteGame(Game game, bool includeRelated) 
    { 
     await GameService.DeleteGame(game, true); 
     await AzureService.SyncGameInfoForGame(game.GameId, true); 
    } 
} 

Ich weiß, dies nicht das beste Beispiel sein könnte, weil es, dass die beiden Service-Anrufe Einheit getestet sind bereits wahrscheinlich ist, aber in anderen Relais Befehle gibt es mehr als nur Aufrufe an Dienste.

Ich dachte, wenn ich so etwas mache, könnte ich alle Geschäftslogik-Sachen testen und niemals einen Test schreiben, der einen RelayCommand aufruft.

Ich bin mir nicht sicher, wie andere Leute Unit-Testing-Modelle nähern, die meisten Informationen, die ich finden konnte, haben Beispiele, die so einfach sind, dass sie nie die Probleme behandeln, denen ich immer wieder begegne.

Antwort

0

Im Allgemeinen würden Sie einen Wrapper erstellen und aufrufen, sodass bei automatisierten Tests diese Stubs stattdessen ausgeführt werden. Ihr gespottetes Init und BeginInvokeOnMainThread werden möglicherweise an verschiedene Implementierungen weitergeleitet.

+0

Danke. Ja, es ist mir eingefallen, warum ich nicht einfach alle statischen Aufrufe in Services umwandele, und dann kann ich sie verspotten, um das zurückzugeben, was ich will, oder eine Testimplementierung bereitzustellen. Ich denke, mein Kopf war zu sehr mit "seinem Handy" eingewickelt, um darüber nachzudenken, was ich normalerweise bei jedem anderen Projekttyp tun würde. Das ist der gleiche Grund, als ich anfing, ich habe es nicht TDD, fing gerade an, Code zu schreiben. – jmichas