I am using SoapCore in a .net core 3.1 app and I have setup an integration testing strategy for controllers that uses a web application factory eg
internal class IntegrationTestApplicationFactory<TStartup> : WebApplicationFactory<TStartup>
where TStartup : class
{
public HttpClient CreateConfiguredHttpClient()
{
var client = this.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false
});
return client;
}
}
This works for my controller integration tests like so:
[Fact]
public async Task OrderDelivery_NoRequestBody_ReturnsBadRequest()
{
var xml = ...
var response = await _client
.PostAsync("http://localhost/api/myController", new StringContent(xml));;
var responseBody = await response.Content.ReadAsStringAsync();
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
responseBody.Should().Contain("Invalid XML");
}
But I am now trying to test some soap endpoints that are working using SoapCore. This is in the startup file:
public static IApplicationBuilder AddSoapCoreEndpoints(this IApplicationBuilder app, IConfiguration
config, IHostEnvironment env)
{
var settings = config.GetSection("FileWSDL").Get<WsdlFileOptions>();
settings.AppPath = env.ContentRootPath;
app.Map("/service", x =>
{
x.UseSoapEndpoint<IService>("/MyService.svc", new BasicHttpBinding(), SoapSerializer.XmlSerializer, false, null, settings);
});
}
The wsdl files are pre-generated.
So then in back in my test project I have added a connected service by browsing to the wsdl file, and written this test body:
var endpoint = new EndpointAddress("http://localhost/service/MyService.svc");
var binding = new BasicHttpBinding(BasicHttpSecurityMode.None);
var client = new MyServiceClient(binding, endpoint);
var response = await client.DoSomething();
I get this exception:
System.ServiceModel.EndpointNotFoundException: 'There was no endpoint listening at http://localhost/service/MyService.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.'
There is no inner exception.
Interestingly though this gives me a 200 by using the same client my controller tests use:
await _client.GetAsync("http://localhost/service/MyService.svc");
Looking at Connected Services > MyService > Reference I can see that there is a port based into the reference, which is a little concerning, but I believe the new endpoint I have specified in the test body should mean that wont be used.
private static System.ServiceModel.EndpointAddress GetEndpointAddress(EndpointConfiguration endpointConfiguration)
{
if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_IMyService))
{
return new System.ServiceModel.EndpointAddress("https://localhost:44399/service/MyService.svc");
}
throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
}
An update based on code in answer from @Craig (OP), but for cases where you don't have a generated WCF-client. Code for
IMySoapSvcwith a complete setup is provided further down in this answer.An alternative to using a SOAP-client, can be to use regular POST requests.
Below is a step-by-step for a simple Hello World SOAP-service with support for both SOAP 1.1 and 1.2. At the end, there are a couple of tests using
WebApplicationFactory, and then usingChannelFactory.Add this Nuget (or newer when available)
The SOAP service
Startup#ConfigureServices
Startup#Configure
Rewrite rules to split between SOAP 1.1/1.2. Put this in file RewriteRules.xml in same folder as Startup.cs.
You'll need this in your project file for RewriteRules.xml
And finally the tests. Here we can see the differences in detail between SOAP 1.1 and SOAP 1.2 requests.
Another approach is to use
ChannelFactoryfor getting a client with a plain host running on port 5000. For this, we'll need to bring up the web environment in a test base class. This approach runs significantly faster thanWebApplicationFactory. See screenshot at the end of this answer.And then the test class. This is pretty standard code.
Screenshot showing elapsed time for tests. The winner is
WcfTestusing host running on port 5000, in second place isBasicTestsusingWebApplicationFactoryand plain POST requests.Update: Tests with NUnit and
WebApplicationFactory(not shown here) runs in a magnitude of 4 times faster due to shorter setup time.Tested using .NET Core 5.