2016-05-19 6 views
0

У меня есть проект XF, который использует Mvvm Light и Ninject. Я пытаюсь отменить и написать модульные тесты для своих моделей просмотра, но у меня все время возникают проблемы, в которых нужно вызвать Xamarin.Forms.Init(), или у меня есть ссылки на Device.BeginInvokeOnMainThread или другой специфический пользовательский интерфейс в RelayCommands.Как организовать код в режиме просмотра Xamarin Forms для модульного тестирования?

Так типичный RelayCommand может выглядеть следующим образом:

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() вызывает некоторые UI вещи, чтобы отобразить индикаторы прогресса. App.Current.Container - это мое ядро ​​Ninject.

Должен ли я смотреть реорганизовать это к чему-то более, как:

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); 
    } 
} 

Я понимаю, что это не может быть лучшим примером, поскольку вполне вероятно, что два вызова службы уже протестирован, но и в другом реле команд происходит больше, чем просто звонки в службы.

Я думал, что если бы я сделал что-то подобное, тогда я смог бы протестировать все вещи бизнес-логики и никогда не писать тест, который вызывает RelayCommand.

Я не уверен, как другие люди приближаются к модели тестирования единичного тестирования. Большая часть информации, которую я смог найти, имеет такие простые примеры, что они никогда не затрагивают проблемы, с которыми я постоянно сталкиваюсь.

ответ

0

Как правило, вы должны создавать и вызывать обертку, чтобы при автоматических тестах эти заглушки выполнялись вместо этого. Ваши издевавшиеся Init и BeginInvokeOnMainThread могут перенаправляться на разные реализации.

+0

Спасибо. Да, мне пришло в голову, почему бы мне просто не включить все статические вызовы в сервисах, а затем я могу издеваться над ними, чтобы вернуть то, что я хочу, или предоставить тестовую реализацию. Думаю, моя голова была слишком обернута «мобильным», чтобы думать о том, что я обычно делал бы в любом другом типе проекта. По той же причине, когда я начал, я не делал TDD, только начал писать код. – jmichas