简体   繁体   English

如何模拟Visual Studio自动生成的SOAP客户端?

[英]How to mock SOAP client that was auto-generated by Visual Studio?

I have an auto-generated SOAP client. 我有一个自动生成的SOAP客户端。 It was generated by visual studio wizard (add connected services -> Microsoft WCF Web Service Reference Provider). 它是由visual studio向导生成的(添加连接服务 - > Microsoft WCF Web服务引用提供程序)。 I would like to mock that client, so when a method is called, a predefined result is going to be returned in a format of the SOAP response. 我想模拟该客户端,因此在调用方法时,将以SOAP响应的格式返回预定义的结果。 Unfortunately, I cannot get it to work - my result is either null (instead of defined in .Returns) or I get an exception. 不幸的是,我无法让它工作 - 我的结果是null(而不是在.Returns中定义)或者我得到一个例外。

I am trying to apply clean architecture in my design. 我想在我的设计中应用干净的架构。 So this SOAP client landed in my infrastructure layer, where I have created a repository for it. 所以这个SOAP客户端落在我的基础架构层中,我已经为它创建了一个存储库。 This repository creates DTOs, so they can be dispatched to my persistence. 此存储库创建DTO,因此可以将它们分派给我的持久性。 The repository receives the SOAP client through dependency injection. 存储库通过依赖注入接收SOAP客户端。 I would also like to have tests for the repository, just to validate that DTOs generation is correct. 我还想对存储库进行测试,只是为了验证DTO的生成是否正确。 So, I would like to mock this SOAP service, so I can feed it to the repository and test the returned DTOs. 所以,我想模拟这个SOAP服务,所以我可以将它提供给存储库并测试返回的DTO。

Auto-generated interface: 自动生成的界面:

    public interface ApplicationSoap
    {
        [System.ServiceModel.OperationContractAttribute(Action = "http://Application/GetAppVersion", ReplyAction = "*")]
        Task<ExtApp.GetAppVersionResponse> GetAppVersionAsync(ExtApp.GetAppVersionRequest request);
    }

and auto-generated client class: 和自动生成的客户端类:

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.1-preview-30514-0828")]
    public partial class ApplicationSoapClient : System.ServiceModel.ClientBase<ExtApp.ApplicationSoap>, ExtApp.ApplicationSoap
    {

        static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);

        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
        System.Threading.Tasks.Task<ExtApp.GetAppVersionResponse> ExtApp.ApplicationSoap.GetAppVersionAsync(ExtApp.GetAppVersionRequest request)
        {
            return base.Channel.GetAppVersionAsync(request);
        }

        public System.Threading.Tasks.Task<ExtApp.GetAppVersionResponse> GetAppVersionAsync(int appVer)
        {
            ExtApp.GetAppVersionRequest inValue = new ExtApp.GetAppVersionRequest();
            inValue.Body = new ExtApp.GetAppVersionRequestBody();
            inValue.Body.appVer = appVer;
            return ((ExtApp.ApplicationSoap)(this)).GetAppVersionAsync(inValue);
        }
    }

I want to mock ApplicationSoapClient and method GetApplicationVersionAsync. 我想模拟ApplicationSoapClient和方法GetApplicationVersionAsync。 After different attempts I ended up the following in my test class: 经过不同的尝试后,我在测试课程中结束了以下内容:

private ExtApp.AppVersion[] _response =
    new ExtApp.AppVersion[]
        {
         new ExtApp.AppVersion
             {
              VersionNumber = 1,
              StartDate = DateTime.Parse("2010-01-01"),
              EndDate = DateTime.Parse("2015-12-31")
             },
        };

private Mock<ExtApp.ApplicationSoap> _client = new Mock<ExtApp.ApplicationSoap>();

public TestClass() 
{
    var body = new ExtApp.GetAppVersionRequestBody(It.IsAny<int>());
    var request = new ExtApp.GetAppVersionRequestRequest(body);
    _client
           .Setup(s => s.GetAppVersionAsync(request))                
           .Returns(
               Task.FromResult(
                   new ExtApp.GetAppVersionResponse(
                       new ExtApp.GetAppVersionResponseBody(_response)))
            );
}

[Fact]
public void TestAppVersionDownload()
{
    var request = new ExtApp.GetAppVersionRequest(
                      new ExtApp.GetAppVersionRequestBody(1));
    var result = _clientSoap.Object.GetAppVersionAsync(request)
                      .Result; //returns null instead of defined in Returns section
    Assert.True(result.Body.GetAppVersionResult.Length == 2);
}

It runs, but Result of the call is null . 它运行,但调用的结果为null I am expecting to get back the object that would have a non-null Body property with the array inside. 我期望在内部返回具有非null Body属性的对象。 I am looking for advice how to make this thing work. 我正在寻找建议如何使这件事工作。

Your SOAP client contract is: 您的SOAP客户合同是:

public interface ApplicationSoap
{
    [System.ServiceModel.OperationContractAttribute(Action = "http://Application/GetAppVersion", ReplyAction = "*")]
    Task<ExtApp.GetAppVersionResponse> GetAppVersionAsync(ExtApp.GetAppVersionRequest request);
}

You use this as a dependency in a repository that could look like this: 您可以将其用作存储库中的依赖项,如下所示:

public class Repository
{
    private readonly IApplicationSoap _client;

    public Repository(IApplicationSoap client) { _client = client; }

    public async Task<AppVersion> GetAppVersionAsync(int version)
    {
        var request = new GetAppVersionRequest(new GetAppVersionRequestBody(version));
        var response = await _client.GetAppVersionAsync(request);
        return new AppVersion 
        {
            Version = response.Body.Version,
            StartDate = response.Body.StartDate,
            EndDate = response.Body.EndDate
        };
    }
}

In this case you may want to test the code that converts your input to a request and the code that converts the response to your DTO. 在这种情况下,您可能希望测试将输入转换为请求的代码以及将响应转换为DTO的代码。 This is the only code that is yours (as opposed to not being generated by the tools). 这是是你的 (而不是未由工具生成的)的唯一代码。 To do so you need to mock (in fact stub ) the SOAP client contract in your Repository test and have it return the response you want: 为此,您需要在Repository测试中模拟(实际上是存根 )SOAP客户端契约,并让它返回您想要的响应:

[Fact]
public async Task GetAppVersionAsync()
{
    // arrange
    var client = new Mock<IApplicationSoap>(); // mock the interface, not the class!
    var result = new AppVersion
    { 
        Version = 1, 
        StartDate = DateTime.Parse("2010-01-01"),
        EndDate = DateTime.Parse("2015-12-31")
    };
    client.Setup(x => x.GetAppVersionAsync(It.IsAny<GetAppVersionRequest>))
          .Returns(Task.FromResult(new GetAppVersionResponse(new GetAppVersionResponseBody(result))));
    var repository = new Repository(soapApp);

    // act
    var dto = await repository.GetAppVersionAsync(1);

    // assert (verify the DTO state)
    Assert.Equal(1, dto.VersionNumber);
    Assert.Equal(new DateTime(2010, 1, 1), dto.StartDate);
    Assert.Equal(new DateTime(2015, 12, 31), dto.EndDate);
}

However... just because you can do this it does not mean that you should. 但是......只是因为你可以做到这一点并不意味着你应该这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 自动生成的代码在Visual Studio 2015中引发很多警告 - auto-generated code throw lots of warning in visual studio 2015 Visual Studio自动生成文件开头的那些字符是什么? - What are those characters at the beginning of Visual Studio auto-generated files? 在 Visual Studio 中包含自动生成的静态内容 - Including auto-generated static content in Visual Studio 如何在WCF中将soap标头添加到自动生成的代理中? - How to add soap header to auto-generated proxies in WCF? 为什么 Visual-Studio 为一个应用程序自动生成 app.config 而不是另一个应用程序? - Why has Visual-Studio auto-generated app.config for one application but not for another? Visual Studio服务参考和自动生成的代理类-为什么不应该在您的类/项目中传递它们? - Visual Studio Service Reference, and Auto-Generated Proxy Classes - Why should they not be passed around your classes/projects? WPF中自动生成的代码显示错误。 (C#,WPF,Visual Studio社区2013) - Auto-generated code in WPF shows error. (C#, WPF, Visual Studio Community 2013) 将Visual Studio生成的Soap客户端发出的请求限制为单线程 - Restrict requests made by Visual Studio generated soap client to single thread 如何在XAML中设置自动生成的元素的样式 - How to style auto-generated elements in xaml 如何编写自动生成的ID的查询 - How to write the query for auto-generated ID
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM