2013-08-09 2 views
8

Я пытаюсь модульного тестирования метода LoginExecute следующего ViewModel с помощью MOQNullReferenceException при вызове метода асинхронной из издевались объекта

public class LoginViewModel : ViewModelBase, ILoginViewModel 
{ 
    INavigationService navigationService; 
    IDialogService dialogService; 
    IAdminService adminService; 

    public RelayCommand LoginCommand { get; set; } 

    private string _productID; 

    public string ProductID 
    { 
     get { return _productID; } 
     set 
     { 
      _productID = value; 
      RaisePropertyChanged("ProductID"); 
     } 
    } 

    public LoginViewModel(INavigationService navigationService, IDialogService dialogService, IAdminService adminService) 
    { 
     this.navigationService = navigationService; 
     this.dialogService = dialogService; 
     this.adminService = adminService; 
     InitializeCommands(); 
    } 

    private void InitializeCommands() 
    { 
     LoginCommand = new RelayCommand(() => LoginExecute()); 
    } 

    public async Task LoginExecute() 
    { 
     await this.navigationService.TestMethod(); 
     this.navigationService.Navigate(typeof(ITherapistsViewModel)); 
    } 

    public void Initialize(object parameter) 
    { 
    } 
} 

INavigationService выглядит следующим образом

public interface INavigationService 
{ 
    Frame Frame { get; set; } 
    void Navigate(Type type); 
    void Navigate(Type type, object parameter); 
    Task TestMethod(); 
    void GoBack(); 
} 

Мой тест выглядит это

[TestMethod()] 
    public async Task LoginCommandTest() 
    { 
     var navigationService = new Mock<INavigationService>(); 
     var dialogService = new Mock<IDialogService>(); 
     var adminService = new Mock<IAdminService>(); 
     LoginViewModel loginVM = new LoginViewModel(navigationService.Object, dialogService.Object, adminService.Object); 

     await loginVM.LoginExecute(); 

     //Asserts will be here 
    } 

Проблема в том, что когда линия

await this.navigationService.TestMethod(); 

Вызывается исключение NullReferenceException. Если тот же метод вызывается без «ожидания», он работает так, как ожидалось. Он также работает нормально, если метод вызывается при нормальной реализации NavigationService (а не в макете). Не могли бы вы помочь мне понять, почему вызов метода async производит NullReferenceException?

ответ

8

Часть Асинхронного шаблона на основе задач - это неявное предположение, что метод никогда не возвращает null.

Это означает, что для всех асинхронных методов вам необходимо высмеять фактическое возвращаемое значение. Я рекомендую использовать Task.FromResult для случая «синхронного успеха», TaskCompletionSource для случая «синхронного исключения» и async лямбда с Task.Delay для случаев «асинхронного успеха/исключения».

2

У меня было что-то похожее на это; У меня была установка с обратным вызовом на Целевую асинхронным, с кодом, как это:

var navigationService = new Mock<INavigationService>() 
    .Setup(s => s.TestMethod()) 
    .Callback(...); 

И бросил неясного NullReferenceException; добавив Returns(Task.CompletedTask) исправили проблему:

var navigationService = new Mock<INavigationService>() 
    .Setup(s => s.TestMethod()) 
    .Returns(Task.CompletedTask) 
    .Callback(...); 

попался на этом сегодня, надеюсь, что поможет кто-то с подобной проблемой.

+0

Этот точный вопрос, сегодня утром, продолжал тянуть мои волосы в течение нескольких часов. –

Смежные вопросы