You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Dec 19, 2018. It is now read-only.
Use Case:
I have written a stateless middleware which uses the address the server is configured to listen on and I want to write test for this middleware.
Example of extension method trying to extract listening addresses from server features:
public static IApplicationBuilder UseServiceFabricRouting(this IApplicationBuilder builder)
{
var serverAddressesFeature = builder.ServerFeatures.Get<IServerAddressesFeature>();
return builder.UseStatelessHttpMiddleware(new ServiceFabricRoutingMiddleware(serverAddressesFeature.Addresses.ToList()));
}
Expected:
I should be able to write tests using the normal aspnetcore convention of using TestServer such as below:
// Arrange
var webHostBuilder = new WebHostBuilder()
.UseUrls("http://localhost:8000/appName/serviceName")
.Configure(b => b
.UseServiceFabricRouting()
.Run(c =>
{
c.Response.StatusCode = (int)HttpStatusCode.OK;
return Task.FromResult(0);
}));
var testServer = new TestServer(webHostBuilder);
// Act
var response = await testServer
.CreateRequest(path: "someOtherService")
.SendAsync("GET");
// Assert
response.StatusCode.Should().Be(HttpStatusCode.Gone);
Actual:
I had to copy the implementation of TestServer into my own ExtendedTestServer class which is burdensome. The whole point is for the tests to feel familiar and not be one off solution so I want my copy class to feel just like TestServer. This means I also have to duplicate the associated RequestBuilder class since it takes concrete dependency of TestServer. Also the TestServer has method which invokes internal constructor of WebSocket so I can't even implement that method.
I think all of the above could be avoided with some very simple tweaks.
More background on server setup and why coping implementation was only solution (extending class or wrapping class does not work)
Normal server setup:
1: UseKestrel() will automatically setup the FeatureCollection
Features = new FeatureCollection();
_serverAddresses = new ServerAddressesFeature();
Features.Set<IServerAddressesFeature>(_serverAddresses);
Middleware would be able to access builder.ServerFeatures.Get<IServerAddresssesFeature>() becuase builder.ServerFeatures would not be null.
TestServer setup:
Step 1 is not done, and then step 2 is no op because addresses is null.
Cannot extend TestServer because you don't have ability to set base classes IServer.Features property.
It only has getter and also there's no way to execute the code before the base class invokes Build()
Cannot wrap TestServer because the internal instance of TestServer is immedately invoking Build()
var host = builder.UseServer(this).Build();
host.Start();
Becuase of this, the internal instance of TestServer (this in line above) is the instance that is used for the Server property in the WebHost. Then it would still be checking the IServer.Features on the TestServer instance not the parent class attempting to wrap it and failing to achieve desired result.
Solutions:
I'm sure there are many ways to get the desired result but here are a few I could think of:
Add another constructor to TestServer to allow taking FeatureCollection as parameter which assigns it before invoking Build / Start
I think this would work but would only solve issue for FeatureCollection, perhaps there are more things people might want to do with TestServer before the web host is built.
Add setter to FeatureCollection and another constructor which doesn't immediately invoke Build / Start. This would allow extending the TestServer class and settings FeatureCollection up in parent constructor and then later invoking build / start.
Would be interested to see what other solutions there are from people more familiar with C# features.
The text was updated successfully, but these errors were encountered:
Use Case:
I have written a stateless middleware which uses the address the server is configured to listen on and I want to write test for this middleware.
Example of extension method trying to extract listening addresses from server features:
Expected:
I should be able to write tests using the normal aspnetcore convention of using
TestServer
such as below:Actual:
I had to copy the implementation of
TestServer
into my ownExtendedTestServer
class which is burdensome. The whole point is for the tests to feel familiar and not be one off solution so I want my copy class to feel just like TestServer. This means I also have to duplicate the associated RequestBuilder class since it takes concrete dependency of TestServer. Also the TestServer has method which invokes internal constructor of WebSocket so I can't even implement that method.I think all of the above could be avoided with some very simple tweaks.
More background on server setup and why coping implementation was only solution (extending class or wrapping class does not work)
Normal server setup:
1:
UseKestrel()
will automatically setup the FeatureCollectionhttps://github.com/aspnet/KestrelHttpServer/blob/632780dd16729298933f96796e6a969f3470d810/src/Microsoft.AspNetCore.Server.Kestrel/KestrelServer.cs#L54
EnsureServer
method will copy all the urls from the settings to ServerAddressesFeatureHosting/src/Microsoft.AspNetCore.Hosting/Internal/WebHost.cs
Line 230 in c8003c0
builder.ServerFeatures.Get<IServerAddresssesFeature>()
becuasebuilder.ServerFeatures
would not be null.TestServer setup:
Step 1 is not done, and then step 2 is no op because
addresses
is null.Cannot extend
TestServer
because you don't have ability to set base classesIServer.Features
property.It only has getter and also there's no way to execute the code before the base class invokes
Build()
Cannot wrap
TestServer
because the internal instance of TestServer is immedately invokingBuild()
Hosting/src/Microsoft.AspNetCore.TestHost/TestServer.cs
Line 25 in b6da89f
Becuase of this, the internal instance of TestServer (
this
in line above) is the instance that is used for theServer
property in the WebHost. Then it would still be checking the IServer.Features on the TestServer instance not the parent class attempting to wrap it and failing to achieve desired result.Solutions:
I'm sure there are many ways to get the desired result but here are a few I could think of:
Add another constructor to TestServer to allow taking
FeatureCollection
as parameter which assigns it before invoking Build / StartI think this would work but would only solve issue for FeatureCollection, perhaps there are more things people might want to do with TestServer before the web host is built.
Add setter to FeatureCollection and another constructor which doesn't immediately invoke Build / Start. This would allow extending the TestServer class and settings FeatureCollection up in parent constructor and then later invoking build / start.
Would be interested to see what other solutions there are from people more familiar with C# features.
The text was updated successfully, but these errors were encountered: