能否在WCF中模拟现有的服务?

本文关键字:服务 模拟 WCF | 更新日期: 2023-09-27 17:49:25

我们有一个第三方供应商服务和一个内部服务来与它沟通。我们的内部服务可以完美地工作,但我被要求编写一个我们供应商服务的后备克隆。目的是能够运行我们的克隆,切换出客户端端点,并允许我们的内部服务继续针对克隆进行测试。

是否有可能重新创建/模拟一个服务,使现有的客户端可以与它通信(无需修改),就像它是原始服务一样?

到目前为止,我已经尝试了三种方法,但没有一种有效。

<标题> 1方法

创建一个简单的服务,引用第三方服务来访问自定义类型并模拟[operation Contract]

当我尝试与此服务通信时,我得到以下错误:

'System.ServiceModel.ActionNotSupportedException'类型的第一次机会异常发生在System.ServiceModel.dll附加信息:由于EndpointDispatcher中的ContractFilter不匹配,带有"Action"的消息无法在接收端处理。这可能是由于合约不匹配(发送方和接收方之间的操作不匹配)或发送方和接收方之间的绑定/安全不匹配。检查发送方和接收方具有相同的合约和相同的绑定(包括安全要求,例如Message, Transport, None)。

没有安全要求,因为我们使用基本的http(没有ssl)。配置文件的服务模型部分和服务行为类属性如下:

<system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="SimpleBinding" />
      </basicHttpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="cloneBehavior" name="MyClone">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="SimpleBinding"
          contract="MyService.IMyService" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost/clone/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="cloneBehavior">
          <serviceMetadata httpGetEnabled="True" httpGetUrl="http://localhost/clone/mex" />
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
</system.serviceModel>

和服务行为

[ServiceBehavior(Name = "CloneService", 
    ConfigurationName = "MyClone", 
    InstanceContextMode = InstanceContextMode.PerCall, 
    AddressFilterMode = AddressFilterMode.Any)]
public class MyService : IMyService
{

一切看起来都很好,我来到了我的第一个死胡同。

<标题> 2方法

去掉我的接口/服务契约,直接从reference.cs文件中生成的接口继承。

当我运行这个服务时,我得到以下错误

系统。InvalidOperationException:操作myMethodA和myMethodB具有相同的操作()。每个操作必须有一个唯一的操作值。

在System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ActionDemuxer

。添加(字符串操作,DispatchOperationRuntime操作)在System.ServiceModel.Dispatcher.ImmutableDispatchRuntime . .男星(DispatchRuntime调度)在System.ServiceModel.Dispatcher.DispatchRuntime.GetRuntimeCore ()在System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpened ()在System.ServiceModel.Channels.CommunicationObject。打开(时间间隔超时)在System.ServiceModel.ServiceHostBase。OnOpen(时间间隔超时)在System.ServiceModel.Channels.CommunicationObject。打开(时间间隔超时)在Microsoft.Tools.SvcHost.ServiceHostHelper。OpenService (ServiceInfo信息)

看一下为这个方法生成的接口,它们都用以下属性装饰:

[System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]

我从msdn的理解是,WCF默认添加模式<namespace>/<service>/<operation>[Response]的唯一操作。

如果我尝试将动作设置为*,那么我可以击中服务(正如预期的那样,使用catch all/unmatched消息处理程序),但我不能击中特定的方法。

尽管如此,手动使所有操作唯一(并符合上述模式),给出这个错误:

客户端配置中的合同' IMyService '与服务合同中的名称不匹配,或者该合同中没有有效的方法。…

我已经在服务契约中明确定义了方法,并且已经进入了第二个死胡同。

<标题> 第三方法

使用wsdl.exe工具从wsdl.exe生成服务。我按照这个SO帖子的说明来生成一个接口并继承它。

我也尝试过使用clientWsdl.wsdl /l:CS /server命令并按照这篇文章中的说明来生成服务本身。

整理生成的代码并运行后,我又回到了原来的错误:

在System.ServiceModel.dll中第一次出现'System.ServiceModel.ActionNotSupportedException'类型异常附加信息:由于EndpointDispatcher中的ContractFilter不匹配,带有"Action"的消息无法在接收端处理。这可能是由于合约不匹配(发送方和接收方之间的操作不匹配)或发送方和接收方之间的绑定/安全不匹配。检查发送方和接收方具有相同的合约和相同的绑定(包括安全要求,例如Message, Transport, None)。

每次尝试时,我都会仔细检查所有配置设置,并在每个阶段更新合约。

在这个阶段,我想知道是否可能。

能否在WCF中模拟现有的服务?

您是否能够使用WCF模拟该服务?我发现自己处于类似的情况,我被要求编写一些集成测试,其中我们的方法调用供应商的web服务。我更倾向于利用Moq来编写适当的单元测试,但我受到以下限制:1)不允许更改我正在测试的方法的签名;2)除了我们发送给服务的内容及其预期的响应外,我对web服务本身一无所知。

@jparram的建议是我接下来的方法。

注意:我宁愿把这篇文章作为评论发布,因为我并没有真正回答你的问题。

如果我理解您的场景,我会创建包装器服务来决定调用哪个服务。听起来这就是你想在情形1中做的事情。因此,您的客户端将始终调用您的包装器服务,并且您的包装器服务将输入映射到您的第三方服务或备份服务的所需输入。

您收到的错误听起来像是代理客户端生成中的问题,其中"Action"没有被映射。查看一下从已知的工作配置中生成的代理代码,并将其与场景1中的代码进行比较。

编辑比较您的服务和"真实"服务生成的代理客户端。关于操作 = "的投诉可能是由于:

[System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="")]

如果您的客户端没有映射到相应的操作