Как обрабатывать да нет DisplayAlert в XUnitTest? - PullRequest
0 голосов
/ 20 декабря 2018

Plaese, помогите мне, как работать с await DisplayAlert в XUnitTest?

Код LoginPageViewModel:

public ICommand LogoutCommand;

public LoginPageViewModel()
{
   LogoutCommand= new RelayCommand(LogoutExecution);
}

async void LogoutExecution()
{
   result = await App.Current.MainPage.DisplayAlert("Alert!","Are you sure you want to logout?", "Yes", "No");
   if (result)
   {
      //Code Execution
      await LogOut();
   }
}

Код XUnitTest:

public class LoginPageViewModelTest
{
        LoginViewModel loginvm;
        public LoginViewModelTest()
        {
            Xamarin.Forms.Mocks.MockForms.Init();            
            var app = new Mock<App>().Object;
            app.MainPage = new Mock<Xamarin.Forms.ContentPage>().Object;
            loginvm = new LoginPageViewModel();
        }        

        [Fact]
        public void LogoutCommandExecuted()
        {
             loginvm.LogoutCommand.Execute(null);
        }
 }

Когда я тестирую LogoutCommandExecuted,Выполнение не завершено после нажатия на эту строку."await App.Current.MainPage.DisplayAlert"

Помогите, пожалуйста, как выполнить «App.Current.MainPage.DisplayAlert» в методе выполнения команды?

1 Ответ

0 голосов
/ 20 декабря 2018

С точки зрения дизайна модель представления тесно связана с проблемами пользовательского интерфейса при вызове DisplayAlert.

Эти проблемы следует абстрагировать, чтобы обеспечить большую гибкость, тестируемость и ремонтопригодность.

Воспользуйтесь преимуществами принципов инверсии зависимостей

Например, создайте абстракцию для представления желаемой функциональности

public interface IDialogService {
    Task<bool> DisplayAlert (String title, String message, String accept, String cancel);

    //...other members
}

Его реализация в основном обернет реальные проблемы пользовательского интерфейса

public class DialogService : IDialogService {
    public Task<bool> DisplayAlert (String title, String message, String accept, String cancel) {
        return App.Current.MainPage.DisplayAlert(title,message, accept, cancel);
    }

    //...other members
}

Модель представления будет явно зависеть от абстракции службы.

Также старайтесь избегать async void за исключением обработчиков событий

public class LoginPageViewModel : ViewModelBase {
    private readonly IDialogService dialog;

    public LoginPageViewModel(IDialogService dialog) {
       LogoutCommand = new RelayCommand(LogoutExecution);
    }

    public ICommand LogoutCommand { get; private set; }

    void LogoutExecution() {
       logOut += onLogOut;
       logOut(this, EventArgs.Empty);
    }

    private event EventHdnalder logOut = delegate { };

    private async void onLogOut(object sender, EventArgs args) {
        logOut -= onLogOut;
        var result = await dialog.DisplayAlert("Alert!","Are you sure you want to logout?", "Yes", "No");
        if (result) {
          //Code Execution
          await LogOut();
       }
    }

    //...
}

Предполагая, что не было других тесно связанных зависимостей,тогда LoginPageViewModel должен быть в состоянии быть изолированным без какого-либо влияния на эффекты, связанные с интерфейсом пользователя.При условии правильно смоделированных зависимостей внедряются в испытуемый субъект.

В производстве система может быть настроена на использование служб зависимостей для внедрения реализаций служб в зависимые классы.

...