2011-02-26 84 views
4

我最近開發了一個Silverlight應用程序,它使用Mark J Millers ClientChannelWrapper與WCF服務層通信(有效地終止服務引用並打包IClientChannel和ClientChannelFactory)。 這裏是接口:Mocking泛型WCF ClientChannelWrapper異步調用

public interface IClientChannelWrapper<T> where T : class 
{ 
    IAsyncResult BeginInvoke(Func<T, IAsyncResult> function); 
    void Dispose(); 
    void EndInvoke(Action<T> action); 
    TResult EndInvoke<TResult>(Func<T, TResult> function); 
} 

包裝物基本上採用一個通用異步服務接口(其可能已經被slsvcutil或手的WCF的ServiceContract後製作的產生)和包裹的調用,以確保在一個信道的情況下故障,會創建一個新頻道。 典型用法是這樣的:

public WelcomeViewModel(IClientChannelWrapper<IMyWCFAsyncService> service) 
    { 
     this.service = service; 
     this.synchronizationContext = SynchronizationContext.Current ?? new SynchronizationContext(); 
     this.isBusy = true; 
     this.service.BeginInvoke(m => m.BeginGetCurrentUser(new AsyncCallback(EndGetCurrentUser), null)); 
    } 

private void EndGetCurrentUser(IAsyncResult result) 
    { 
     string strResult = ""; 
     service.EndInvoke(m => strResult = m.EndGetCurrentUser(result)); 
     this.synchronizationContext.Send(
        s => 
        { 
         this.CurrentUserName = strResult; 
         this.isBusy = false; 
        }, null); 
    } 

這一切工作正常,但現在我想進行單元測試,其使用ClientChannelWrapper視圖模型。 我已經設置了起訂量使用一個簡單的單元測試:

[TestMethod] 
    public void WhenCreated_ThenRequestUserName() 
    { 
     var serviceMock = new Mock<IClientChannelWrapper<IMyWCFAsyncService>>(); 
     var requested = false; 

     //the following throws an exception 
     serviceMock.Setup(svc => svc.BeginInvoke(p => p.BeginGetCurrentUser(It.IsAny<AsyncCallback>(), null))).Callback(() => requested = true); 


     var viewModel = new ViewModels.WelcomeViewModel(serviceMock.Object); 
     Assert.IsTrue(requested); 
    } 

我得到NotSupportedException異常:不支持的表達式:P => p.BeginGetCurrentUser(IsAny(),空)。我對Moq很新,但我猜想使用通用服務接口的ClientChannelWrapper存在一些問題。試圖把我的頭圍繞這個相當長一段時間,也許有人有一個想法。謝謝。

回答

3

對不起回答我自己的問題,但我終於明白了。 以下是詳細信息:

由於在Mark I Millers的IClientChannelWrapper具體實現中,解決方案經常出現在我面前。在那裏,他提供了兩個構造函數,在WCF端點名稱(這是我在生產代碼中使用)的字符串一個了結,第二個:

public ClientChannelWrapper(T service) 
    { 
     m_Service = service; 
    } 

事不宜遲,這裏是我的新的測試代碼:

[TestMethod] 
    public void WhenCreated_ThenRequestUserName() 
    { 
     var IMySvcMock = new Mock<IMyWCFAsyncService>(); 
     var serviceMock = new ClientChannelWrapper<IMyWCFAsyncService>(IMySvcMock.Object); 
     var requested = false; 

     IMySvcMock.Setup(svc => svc.BeginGetCurrentUser(It.IsAny<AsyncCallback>(), null)).Callback(() => requested = true); 
     var viewModel = new ViewModels.WelcomeViewModel(serviceMock); 

     Assert.IsTrue(requested); 
    } 

所以我基本上忽略了ChannelWrapper的接口,並用我的WCF服務接口的Mock對象創建它的一個新實例。然後,我將設置調用的服務將在我的視圖模型的構造函數中使用,如上所示。現在一切都像魅力一樣運作。我希望這對某人有用,因爲我認爲ClientChannelWrapper的想法對於Silverlight < - > WCF通信非常有用。請隨時評論這個解決方案!

+2

不要遺憾回答你的問題。在其他人提供可能的解決方案之前,您找到了可以解決問題的答案。爲什麼你不應該與其他面臨類似問題的人分享這個答案? – froeschli 2011-02-27 12:37:59