2013-08-09 9 views
8

की बुला async विधि मैं इकाई परीक्षण करने के लिए कोशिश कर रहा हूँ MOQNullReferenceException जब मज़ाक उड़ाया वस्तु

का उपयोग कर निम्नलिखित ViewModel की LoginExecute विधि
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 कहा जा रहा है। यदि एक ही विधि को "प्रतीक्षा" के बिना बुलाया जाता है तो यह अपेक्षा के अनुसार काम करता है। यह सामान्य काम करता है अगर विधि सामान्य नेविगेशन सेवा कार्यान्वयन (इसे एक नकली नहीं) पर बुलाया जा रहा है। क्या आप कृपया मुझे समझने में मदद कर सकते हैं कि एसिंक विधि कॉल NullReferenceException क्यों उत्पन्न कर रहा है?

उत्तर

8

कार्य-आधारित असीमित पैटर्न का हिस्सा एक अंतर्निहित धारणा है कि विधि कभी भी null वापस नहीं आती है।

इसका मतलब है कि सभी असीमित तरीकों के लिए, आपको वास्तविक वापसी मूल्य का नकल करना होगा। मैं "सिंक्रोनस सफलता" केस के लिए Task.FromResult, "सिंक्रोनस अपवाद" केस के लिए TaskCompletionSource और लैम्ब्डा को Task.Delay के साथ "एसिंक्रोनस सफलता/अपवाद" मामलों के लिए उपयोग करने की अनुशंसा करता हूं।

2

मेरे पास ऐसा कुछ था; मैं इस तरह कोड के साथ एक async कार्य पर एक कॉलबैक के साथ एक सेटअप था,:

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

इस सटीक मुद्दे ने आज सुबह मेरे बालों को घंटों तक खींच लिया। –

संबंधित मुद्दे