我最近开发了一个Silverlight应用程序,它使用Mark J Millers ClientChannelWrapper<T>
与WCF服务层进行通信(有效地终止服务引用并包装IClientChannel
和ClientChannelFactory
)。
这是界面:
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);
}
Wrapper基本上采用通用异步服务接口(可能由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
的视图模型进行单元测试。
我使用Moq设置了一个简单的单元测试:
[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 =&gt; p.BeginGetCurrentUser(IsAny(),null)。
我对Moq很新,但我想使用通用服务接口的ClientChannelWrapper
存在一些问题。试着把这个问题包围了很长一段时间,也许有人有个主意。谢谢。
答案 0 :(得分:3)
很抱歉回答我自己的问题,但我终于明白了。 以下是详细信息:
通常,解决方案就在我面前,因为它是在Mark J 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&lt; - &gt; WCF通信。请随时评论此解决方案!