测试一个WCF Web服务?

23
我希望为一个WCF服务创建一个测试类。我认为这称为“模拟”?我不确定我认为的方法是否正确。例如,我已经获得了一个WCF服务的URL:
http:://somesite.com/wcf/RealService.svc

而且:

http:://somesite.com/wcf/RealService.svc?wsdl

所以,我并没有像将RealService.svc作为Service Reference添加到我的项目中,而是在我的项目中添加了一个名为Service1的新的空的WCF Service

然后,我想使用wsdl.exe(或者可能是svcutil.exe?)工具从WSDL URL生成一个接口:http:://somesite.com/wcf/RealService.svc?wsdl

然后我打开Service1.cs文件,让它继承自生成的interface,而不是继承自IService1.cs

然后,在我的应用程序中,我不再调用真正的服务,而是直接调用我的Service1类。这就是模拟Web服务的工作方式吗..?

同时,我还需要弄清楚如何使用svcutil工具实际生成一个interface(我已经读到不能使用wsdl.exe来处理WCF服务?)。所以,任何关于这方面的提示都非常欢迎!


http://www.codeproject.com/Articles/318260/How-to-Mock-a-WCF-Service - Zaki
@Zaki - 我认为那篇文章的标题可能应该是“如何不去模拟一个WCF服务”。 - mungflesh
2个回答

21
许多方面需要涉及,我将尝试指引您正确的方向:
  • 如果您想要测试(即传递输入,验证输出)您的WCF服务,请使用Visual Studio GUI工具 WCF Test Client (MSDN文章here)。

  • 如果您想要模拟您的WCF服务(即对使用WCF服务的组件进行单元测试),请使用像NMock2这样的模拟框架,它允许您模拟服务接口(相关SO线程here)。如果您不想使用外部框架,则可以手动编写模拟(通过实现接口),但这更加复杂。

  • 如果您想要对WCF服务进行单元测试(即为服务、业务、数据等编写单元测试),请使用流行的模拟框架(相关SO线程here)。

  • 要为WCF服务生成代理,请使用svcutil.exe命令行实用程序(MSDN文章here),正如您猜测的那样。此实用程序带有各种选项(语言、名称空间、配置文件等),因此请注意它们。

希望这有所帮助。

除了将服务引用添加到新的C#项目中,该操作将为您生成客户端代理之外,使用svcutil.exe有什么区别。为什么要使用它而不是只向项目添加引用,这样做会做同样的事情,对吗?或者也许不是。我正在尝试更多地了解关于在WCF中测试客户端代理的内容。 - PositiveGuy
@CoffeeAddict - 两种方法(项目引用或svcutil)都完美地工作。在前一种方法中,Visual Studio会进行一些“幕后魔术”并生成一堆文件,这样更容易更新。然而,在后一种方法中,您只需处理一个代理文件,但需要再次运行命令以进行更新。我更喜欢后者,因为我喜欢将一个代理文件提交到我的源代码控制中,并且我不介意通过命令行进行更新过程。有道理吗? - Channs

3
您可以使用 svcutil.exe (从 Visual Studio: 添加服务引用...)生成您的代理。这将生成您的客户端代理和一个服务接口
例如,对于您的服务 http:://somesite.com/wcf/RealService.svc?wsdl,我们将获得:
  • IRealService(接口)
  • RealServiceClient(实现IRealService并扩展System.ServiceModel.ClientBase)
您可以创建一个模拟类来实现您的服务接口(IRealService)。
在应用程序中,当您要调用服务时,可以使用工厂或IOC容器,而不是实例化具体的服务客户端(RealServiceClient)。
这样,您就可以决定应用程序(或模块/组件)使用哪个实例:运行时使用真实服务,测试时使用模拟服务。

我曾经看到有人将他们的WCF项目引用添加到C#测试项目中,甚至不需要在C#项目中添加服务引用,这是可能的吗?是否正确?此外,模拟的目的不是根本不使用服务实例,即使您正在注入它吗?它应该是隔离的,所以模拟框架会为您创建一个虚假的服务实例或类似的东西吗? - PositiveGuy
当您调用“添加服务引用...”命令时,您将获得一些生成的代码,可以将其用作“常规代码”。我的意思是,您可以引用生成代理类的程序集并在不需要再次调用“添加服务引用...”命令的情况下使用它们(例如,在测试项目中)。问题在于,契约(“接口”)及其实现(“类”)生成在同一个文件(因此是同一程序集)中,但是您可以在测试项目中创建模拟实现。 - polkduran
只要您的主应用程序处理“接口”而不是具体实现,您就可以决定注入“真正”的服务实现或“模拟”类,例如在测试时或者当您不想调用“真正”的服务(例如原型设计时)。这就是“模拟”的意义所在。 - polkduran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接