Woot、この問題に 2 日間取り組んだ後、私は一緒に暮らすことができる解決策を見つけました。
上記のコード例に見られるように、このヘルパー クラスを使用して WCF 接続を管理します (Close と 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();
}
}
}
}
このテスト フックを Service に追加することで、テストで T を実装する任意のオブジェクトに忍び込むことができます。
MockWebsiteService mockmodel = new MockWebsiteService();
Service<WcfInterface.IServiceWebsites>.DebugOverride = mockmodel;
// run my tests here
私にとって、これは WCF サービスをモックする非常に良い方法です!
PS: #if DEBUG が原因で、リリース時にテストがコンパイルされないことは承知しています。気にするなら追い出してください。