Woot,在解决这个问题两天后,我找到了一个我可以忍受的解决方案:
如上面的代码示例所示,我使用这个帮助类来管理我的 WCF 连接(因为正确处理了 Close vs Abort):
public delegate void UseServiceDelegate<T>(T proxy);
public static class Service<T>
{
public static ChannelFactory<T> _channelFactory;
public static void Use(UseServiceDelegate<T> codeBlock)
{
if (_channelFactory == null)
_channelFactory = new ChannelFactory<T>("AlyzaServiceEndpoint");
IClientChannel proxy = (IClientChannel)_channelFactory.CreateChannel();
bool success = false;
try
{
codeBlock((T)proxy);
proxy.Close();
success = true;
}
finally
{
if (!success)
{
proxy.Abort();
}
}
}
}
正如我的问题所见,这是我的 ViewModel 中使用此类的方式:
Service<Sam.Alyza.WcfInterface.IServiceWebsites>.Use(alyzaSvc =>
{
rc = new List<Sam.Alyza.WcfInterface.Website>(alyzaSvc.GetSites());
});
要模拟 WCF 接口,我需要创建和托管模拟 WCF 服务,更改所有连接字符串。很多工作只是为了添加一些测试。
我找到了一种更简单的方法:创建一个实现接口的模拟服务很简单:
public class MockWebsiteService : WcfInterface.IServiceWebsites
{
internal List<Sam.Alyza.WcfInterface.Website> _websites = new List<Sam.Alyza.WcfInterface.Website>();
internal int _GetSitesCallCount;
IEnumerable<Sam.Alyza.WcfInterface.Website> Sam.Alyza.WcfInterface.IServiceWebsites.GetSites()
{
_GetSitesCallCount++;
return _websites;
}
}
唯一的问题是:如何让 ViewModel 调用这个模拟类而不是服务?
解决方案:Service.Use() 确实管理连接。通过添加覆盖连接管理的功能,我可以将自己的 WCF 模拟对象偷偷带入 Service.Use()。
为此,我需要一种方法让 Service.Use() 调用 WCF 以外的东西(查看#DEBUG 部分):
public static class Service<T>
{
#if DEBUG
public static T DebugOverride = default(T);
#endif
public static ChannelFactory<T> _channelFactory;
public static void Use(UseServiceDelegate<T> codeBlock)
{
#if DEBUG
if (!Object.Equals(DebugOverride, default(T)))
{
codeBlock(DebugOverride);
return;
}
#endif
if (_channelFactory == null)
_channelFactory = new ChannelFactory<T>("AlyzaServiceEndpoint");
IClientChannel proxy = (IClientChannel)_channelFactory.CreateChannel();
bool success = false;
try
{
codeBlock((T)proxy);
proxy.Close();
success = true;
}
finally
{
if (!success)
{
proxy.Abort();
}
}
}
}
通过将此测试钩子添加到服务中,我可以在我的测试中潜入任何实现 T 的对象:
MockWebsiteService mockmodel = new MockWebsiteService();
Service<WcfInterface.IServiceWebsites>.DebugOverride = mockmodel;
// run my tests here
对我来说,这是模拟 WCF 服务的好方法!
PS:我知道由于#if DEBUG,测试不会在发布中编译。如果你在乎,就把他们踢出去。