[英]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.