2013-08-09 52 views
8

Tôi đang cố gắng để kiểm tra đơn vị phương pháp LoginExecute của ViewModel sau sử dụng MOQNullReferenceException khi gọi phương pháp async của chế giễu đối tượng

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

Các INavigationService trông như thế này

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

thử nghiệm của tôi trông giống như này

[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 
    } 

Vấn đề là khi dòng

await this.navigationService.TestMethod(); 

được gọi là NullReferenceException đang được ném. Nếu cùng một phương pháp được gọi là không "chờ đợi", nó hoạt động như mong đợi. Nó cũng hoạt động ok nếu phương thức đang được gọi trên thực thi NavigationService bình thường (không phải là một mô hình của nó). Bạn có thể vui lòng giúp tôi hiểu tại sao cuộc gọi phương thức async đang tạo ra NullReferenceException?

Trả lời

8

Một phần của Mẫu không đồng bộ dựa trên nhiệm vụ là một giả định ngầm rằng phương pháp không bao giờ trả về null.

Điều này có nghĩa là đối với tất cả các phương thức không đồng bộ, bạn sẽ cần giả lập giá trị trả lại thực tế. Tôi khuyên bạn nên sử dụng Task.FromResult cho trường hợp "đồng bộ thành công", TaskCompletionSource cho trường hợp "ngoại lệ đồng bộ" và async lambda với Task.Delay cho trường hợp "thành công không đồng bộ/ngoại lệ".

2

Tôi đã có một cái gì đó tương tự như thế này; Tôi đã có một thiết lập với một callback trên một nhiệm vụ async, với mã như thế này:

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

Và nó đã ném một NullReferenceException che khuất; thêm số Returns(Task.CompletedTask) khắc phục sự cố:

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

Đã bắt gặp điều này ngày hôm nay, hy vọng sẽ giúp ai đó có vấn đề tương tự.

+0

Vấn đề chính xác này, sáng nay, giữ tóc tôi kéo dài hàng giờ liền. –