2010-08-24 43 views
3

Silverlight工具包包含單元測試功能,它允許在異步調用遠程服務的MVVM應用程序中測試類,例如ViewModels。集成測試在WPF MVVM應用程序中異步調用WCF服務的ViewModel

我希望能夠對實際服務而不是模擬實例執行我的ViewModel集成測試。

是否支持異步單元/集成測試的WPF應用程序?

更新:

在這一天結束我的解決方案相結合ktutnik和Alex Paven的建議。我寫了一個小助手類,它增加了一些語法糖:

public static class AsyncMethod 
{ 
    public delegate void AsyncMethodCallback(AsyncMethodContext ctx); 

    public static void Call(AsyncMethodCallback cb) 
    { 
     // create the sync object and make it available via TLS 
     using (var syncObject = new AutoResetEvent(false)) 
     { 
      // call the decorated method 
      cb(new AsyncMethodContext(syncObject)); 
     } 
    } 
} 

/// <summary>Asnc Method Callback Synchronization Context</summary> 
public class AsyncMethodContext 
{ 
    public AsyncMethodContext(EventWaitHandle syncObject) 
    { 
     this.syncObject = syncObject; 
    } 

    private readonly EventWaitHandle syncObject; 

    /// <summary> 
    /// Waits for completion. 
    /// </summary> 
    public void WaitForCompletion() 
    { 
     syncObject.WaitOne(); 
    } 

    /// <summary> 
    /// Signals the current operation as complete 
    /// </summary> 
    public void Complete() 
    { 
     syncObject.Set(); 
    } 
} 

這裏有一個樣本測試案例與微軟的Rx擴展的利用相結合:

[TestMethod] 
public void TestGuestLogin() 
{ 
    AsyncMethod.Call((ctx) => 
    { 
     var vm = ServiceLocator.Get<LoginDialogViewModel>(); 

     // setup VM data 
     vm.Username = "guest"; 
     vm.Password = "guest"; 
     vm.AutoLogin = false; 
     GenericInfoEventArgs<LoginDialogViewModel.LoginRequestResult> loginResult = null; 

     // pre-flight check 
     Assert.IsTrue(vm.LoginCmd.CanExecute(null)); 

     // create Observable for the VM's LoginRequestComplete event 
     var loginEvent = Observable.FromEvent<GenericInfoEventArgs<LoginDialogViewModel.LoginRequestResult>>(vm, "LoginRequestComplete").Do((e) => 
     { 
      Debug.WriteLine(e.ToString()); 
     }); 

     // subscribe to it 
     var loginEventSubscription = loginEvent.Subscribe((e) => 
     { 
      loginResult = e.EventArgs; 

      // test complete 
      ctx.Complete(); 
     }); 

     // set things in motion 
     using (loginEventSubscription) 
     { 
      vm.LoginCmd.Execute(null); 
      ctx.WaitForCompletion(); 

      Assert.IsTrue(loginResult.Info.Success, "Login was not successful"); 
     } 
    }); 
} 

回答

3

我打獵了這麼久的時間功能但運氣不佳。

不是一個乾淨的解決方案,但它對我來說很有用。我通常使用ManualResetEvent,因此在異步完成之前測試過程不會崩潰。這裏的理念是:

//set false for initial state 
resetEvent = new ManualResetEvent(false); 
//do the test 
myObjec.MakeMeHappyAssync(); 
//just wait until its state set 
//when your call done 
resetEvent.WaitOne(); 
//do assertion here 

而且在某處你的Complete方法或故障的方法,你只需撥打

resetEvent.Set(); 

無論如何,如果你發現對功能的任何新信息,請讓我知道

最好的方面

+0

不幸的是,這就是我的解決方案最終解決的問題。看到我更新的帖子。 – 2010-08-27 09:02:58

1

你可以看看Reactive Extensions,它現在包含在.Net Framework 4中,假設你正在使用它;還有3.5和Silverlight的版本。他們允許一些很好的異步編碼,我之前在單元測試中使用過它們。有關討論此問題的博客文章,請參見here

+0

優秀的建議。閱讀和使用該庫是一個真正令人大開眼界。 – 2010-08-27 09:02:16