2013-08-09 2 views
8

의 호출 비동기 방법은 내가 단위 테스트에 MOQNullReferenceException이 조롱 객체

를 사용하여 다음 뷰 모델의 LoginExecute 방법을 시도하고 때 INavigationService 내 테스트의 모습이

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

과 같은

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

[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이 발생합니다. "await"없이 같은 메서드가 호출되면 예상대로 작동합니다. 메서드가 일반 NavigationService 구현 (모의가 아닌)에서 호출되는 경우에도 정상적으로 작동합니다. 비동기 메서드 호출이 NullReferenceException을 생성하는 이유를 이해해 주시겠습니까?

답변

8

작업 기반 비동기 패턴의 일부는 메서드가 null을 반환하지 않는다는 암묵적인 가정입니다.

즉, 모든 비동기 메소드에 대해 실제 반환 값을 조롱해야합니다. "동기 성공"의 경우 Task.FromResult, "동기 예외"의 경우 TaskCompletionSource, "비동기 성공/예외"의 경우 인 async 람다를 사용하는 것이 좋습니다.

2

나는 이와 비슷한 것을 가지고있다. 이 같은 코드로, 비동기 작업에 콜백과 함께 설치했다 :

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

그리고 그것은 모호한 NullReferenceException이를 던졌다;

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

이 오늘에 의해 체포 당함, 비슷한 문제를 가진 사람을 도움이 될 것입니다 희망하십시오 Returns(Task.CompletedTask)이 문제를 해결 덧붙였다.

+0

이 정확한 문제는 오늘 아침 내 머리카락을 몇 시간 동안 계속 내 보냈습니다. –

관련 문제