2011-02-26 79 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