如何在C#中模拟肥皂服务类



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

我的类是"自定义名称",它调用了soapservice调用,该调用返回自定义的自定义名称。我想伪造肥皂服务调用以返回一些fakedata。

自定义名称类:

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获取数据?

我不清楚如何做到..

,而不是直接引用WebService,因此尝试模拟Web服务本身,而是创建一个界面,该界面具有WebService提供的功能。

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

然后,进行两个实现。一个调用实际网络服务,您可以用于测试:

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);
}

后者授权的班级只是如何模拟班级的一个示例,但我个人更喜欢。

您的方法有几个问题。对于初学者,您只能伪造虚拟方法(或抽象方法或在接口上定义的方法(。我认为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);

这将确保您的假返回someCustomerName,只要调用GetCustomerName。我从假货上更改了someCustomerName,因为您可能不需要它是假的 - 如果很容易创建CustomerName对象以从您的假服务中返回,我就是这样。只有您需要改变其行为,或者几乎无法创建它,我才会使用假。

配置了伪造后,您应该在生产类中调用某些方法(您说的称为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