ユニットテストWCFサービスの点滴


ユニットテストで自分で書いたWCFサービスを呼び出したことはありますか?
サービスリファレンスを追加してテストするのではないでしょうか...
ここでは、自分のWCFサービスを直接呼び出す非常に簡単な方法を紹介します.
1.サービスの開始
まず、自分のWCFサービスを起動する必要がありますが、サービスが起きていなければ、どのように呼び出しても無駄です.
もちろん、これらのコードは大同小異なので、いっそ拡張方法にカプセル化します.
        public static void RunWcfService(this Type type, Action action)

        {

            var host = new ServiceHost(type);

            try

            {

                host.Open();

                action();

            }

            finally

            {

                if (host.State == CommunicationState.Faulted)

                    host.Abort();

                else

                    host.Close();

            }

        }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
ここでは、このタイプがサービスの実装であり、プロファイルに関連する構成(configの必要な情報をテストエンジニアリングのapp.configにコピーする必要がある)がある場合に、この拡張方法を直接タイプに拡張方法を追加します.
Action内の実行コードの場合、このサービスは常にオープン状態にあります.
2.クライアントの作成
サービス側だけではだめですが、クライアントが必要です.クライアントのコードを生成する必要がありますか?
Clientのエージェントクラスを生成する必要があるなら、また自分で迷惑をかけているのではないでしょうか.WCFクライアントはChannelFactoryで生成することもできることを忘れないでください.
        public static void InvokeWcfClient<TChannel>(

            this Uri uri, Binding binding, Action<TChannel> action)

            where TChannel : class

        {

            TChannel client = ChannelFactory<TChannel>.CreateChannel(

                binding, new EndpointAddress(uri));

            var co = (ICommunicationObject)client;

            try

            {

                co.Open();

                action(client);

            }

            finally

            {

                if (co.State == CommunicationState.Faulted)

                    co.Abort();

                else

                    co.Close();

            }

        }

ここでTChannelはサービス契約(つまり通常のインタフェース)であり、BindingはサービスのBinding方式であり、サービス側が標準のBindingを使用している場合は、newの標準Bindingを直接newすればよい(例えばNetTcpBinding)、Uriはサービス構成でリスニングされるアドレスである.
3.例.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
この2つの拡張方法があります.ユニットテストの書き方を見てみましょう.
        [ServiceContract]

        public interface IHelloWorld

        {

            [OperationContract]

            string SayHello();

        }



        public class HelloWorld

            : IHelloWorld

        {

            public string SayHello()

            {

                return "Hello world";

            }

        }



        [TestMethod]

        public void TestSayHello()

        {

            Uri uri = new Uri("net.tcp://localhost:8765/vwxyzh/helloworld/");

            typeof(HelloWorld).RunWcfService(() =>

            {

                uri.InvokeWcfClient<IHelloWorld>(new NetTcpBinding(),

                    client =>

                    {

                        Assert.AreEqual("Hello world", client.SayHello());

                    });

            });

        }

簡単ではないでしょうか.もちろん、HelloWorldの構成を忘れないでください.そうしないと、サービスを作成するときに構成が見つからないため、異常になります.