有没有试过在单元测试中调用自己写的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();
            }
        }

     这里直接在类型上添加了一个扩展方法,当这个类型是一个服务的实现,并且配置文件中有相关的配置(需要把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就可以了(例如:NetTcpBinding),Uri是服务配置中侦听的的地址。

3.例子

    现在有了这两个扩展方法,看看怎么写单元测试吧:

        [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的配置,否则在创建服务的时候会因为找不到配置而导致异常。

posted on 2010-03-30 12:49  Zhenway  阅读(2594)  评论(1编辑  收藏  举报