【问题标题】:How to mock a SOAP Service class in C#如何在 C# 中模拟 SOAP 服务类
【发布时间】:2017-06-07 18:37:04
【问题描述】:

我想在这里伪造 getCustomerName 服务调用并用伪造的数据模拟它

我的类是“CustomerName”,它调用 SOAPService 调用,该调用返回 CustomerNumber 的 CustomerName。我想伪造 SOAPService 调用以返回一些假数据。

客户名称类:

using (WebService.WebServiceClient CustomerData = new WebService.WebServiceClient ())
{
      WebServiceClient.TestResponse resp = CustomerData.getCustomerName(customerNumber);
      resp.CustomerName;
}

我试过做这些

var FakeWebService = A.Fake<WebServiceClient>();
var FakeCustomerName=A.Fake<CustomerName>();

然后我在这里伪造了呼叫,虚假响应是一些价值

    A.CallTo(WebServiceClient.CustomerNumber).WithNonVoidReturnType().Returns(FakeResponse); 
fakeCustomerName = FakeCustomerData.GetCustomerName(CustomerNumber);

我面临的问题是它从实际端点而不是 fakedata 获取数据?

我不清楚该怎么做..

【问题讨论】:

    标签: c# fakeiteasy


    【解决方案1】:

    与其直接引用网络服务并因此尝试模拟网络服务本身,不如创建一个包含网络服务提供的功能的接口。

    public interface ICustomerData
    {
        CustomerName GetCustomerName(CustomerNumber number);
    }
    

    然后,进行两个实现。一种调用实际的 Web 服务,另一种可用于测试:

    public class CustomerData : ICustomerData
    {
        CustomerName GetCustomerName(CustomerNumber number)
        {
            return CustomerData.GetCustomerName(number);
        }
    
        public CustomerData()
        {
            CustomerData = new WebService.WebServiceClient ();
        }
        private WebService.WebServiceClient CustomerData;
    }
    
    
    public class DelegatedCustomerData : ICustomerData
    {
        public Func<CustomerNumber,CustomerName> GetCustomerName {get;set;}
    
    
        CustomerName ICustomerData.GetCustomerName(CustomerNumber number) => GetCustomerName(number);
    
    }
    

    后一个委托类只是一个关于如何模拟类的示例,但我个人更喜欢它。

    【讨论】:

      【解决方案2】:

      您的方法存在几个问题。对于初学者,您只能伪造虚拟方法(或抽象方法,或定义在接口上的方法)。我假设WebService.WebServiceClient.getCustomerName 不是虚拟的,所以这里有一个替代@Micael 的答案,可以帮助你解决这个问题。我过去用过很多次:

      就像 Micael 所说,创建一个接口来代替 Web 服务提供的功能。

      public interface ICustomerData
      {
          CustomerName GetCustomerName(CustomerNumber number);
      }
      

      然后你可以像他一样让你的生产合作者CustomerData,或者如果WebService.WebServiceClient没有被密封,你可以这样做:

      public class CustomerData: WebService.WebServiceClient, ICustomerData
      {}
      

      您需要找到一种方法来为您的生产代码提供ICustomerData 的实现,以便您可以在生产期间使用实际实现并在测试期间使用假的实现,我现在正在谈论这个:

      第二个问题是,在您的测试中,您试图伪造对WebServiceClient.CustomerNumber 的调用,这对我来说感觉像是一种类型,而不是您正在处理的实际对象。按照我们上面的步骤,你想伪造ICustomerData 接口:

      var fakeCustomerData = A.Fake<ICustomerData>();
      var someCustomerName = getACustomerNameSomehow();
      
      A.CallTo(() => fakeCustomerData.GetCustomerName(A<CustomerNumber>.Ignored)
              .Returns(someCustomerName);
      

      这将确保无论何时调用 GetCustomerName,您的假货都会返回 someCustomerName。我将 someCustomerName 从一个假的更改为因为您可能不需要它是一个假的 - 如果创建一个 CustomerName 对象从您的假服务返回很容易,我会这样做。只有当你需要改变它的行为,或者它几乎不可能创建时,我才会使用假的。

      配置fake之后,你应该在你的生产类上调用一些方法(你说它被称为CustomerName,就像从GetCustomerName返回的类型一样?),最终将调用ICustomerData协作者。在您的原始代码中,您直接在伪造品上调用一个方法,该方法仅测试伪造品,而不是您自己的代码。因此,您可能会有类似

      的内容
      var customerNameService = new CustomerName(fakeCustomerData);
      
      var foundCustomerName = customerNameService.GetACustomerNameFromANumber(someCustomerNumber);
      // in my imagination, GetACustomerNameFromANumber calls ICustomerData.GetCustomerName
      
      // now do something to check if the foundCustomerName is right, or whatever
      

      【讨论】:

      • FakeCustomerData 正在调用 WebService..我在这里有点困惑..我想模拟在接口“ICustomerData”中声明的 WebService 因为我在这里写的例子几乎是不同的从原来的..我很困惑(据我所见,我没有一个界面可以强制它分别返回生产数据和假数据
      • 我不完全理解你的评论,但让我试着解释一下。执行您想要/需要的操作的常用方法是声明一个具体类(您将对其进行测试),该类以接口的形式接受注入的协作者(通常通过构造函数或属性注入)。然后在生产代码中注入协作者(Web 服务)的具体实现,在测试中注入伪造的接口。我希望这有帮助。我对示例 sn-ps 以及您的变量和类名感到困惑,或者我会尝试提供一个完整的示例。
      • 无论如何它都不会工作,因为我调用的服务不是虚拟的,这是我尝试使用模拟、假冒的私人方式,但没有任何效果!
      • @Shan,如果您无法选择将其设为非私有,并且您真的想模拟它,您可以使用 TypeMock Isolator 或类似产品。虽然一种常见的替代方法是创建一个在您的代码中使用的接口,并让一个非常苗条的类实现该接口并委托给您无法模拟的协作者。
      • +4 年 @BlairConrad 我确实尝试过,您的解决方案效果很好。
      猜你喜欢
      • 1970-01-01
      • 2018-06-21
      • 2023-01-13
      • 2020-03-04
      • 1970-01-01
      • 1970-01-01
      • 2018-12-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多