I want to create WebApplication fixture so I can share it among my integration tests. That's how it looks:
public class WebAppFixture : IDisposable
{
private readonly TestServer _server;
const string WsHubPath = "/";
public WebAppFixture()
{
var builder = WebApplication.CreateBuilder();
builder.Services.AddUltraWs()
.AddWsHub<TestWsHub>();
var app = builder.Build();
app.UseWebSockets();
app.MapUltraWs<TestWsHub>(WsHubPath);
_server = app.GetTestServer();
HttpClient = app.GetTestClient();
}
public HttpClient HttpClient { get; }
public Uri WsHubUri => new Uri(_server.BaseAddress + WsHubPath);
public WebSocketClient CreateWebSocketClient() => _server.CreateWebSocketClient();
public void Dispose()
{
_server.Dispose();
HttpClient.Dispose();
}
}
But when I want to use it in my test class:
public class WsHubTests : IClassFixture<WebAppFixture>
{
private readonly WebAppFixture _webAppFixture;
public WsHubTests(WebAppFixture webAppFixture)
{
_webAppFixture = webAppFixture;
}
}
Then I get following exception:
System.AggregateException : One or more errors occurred. (Unable to cast object of type 'Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl' to type 'Microsoft.AspNetCore.TestHost.TestServer'.) (The following constructor parameters did not have matching fixture data: WebAppFixture webAppFixture) ---- System.InvalidCastException : Unable to cast object of type 'Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl' to type 'Microsoft.AspNetCore.TestHost.TestServer'. ---- The following constructor parameters did not have matching fixture data: WebAppFixture webAppFixture
How to fix it? What am I doing wrong?
Your problem does not lie with the IClassFixture<WebAppFixture>
and the accompanying constructor parameter but with what happens in the WebAppFixture
when it's constructed. A hint to what is going wrong is given in the error you have posted.
(Unable to cast object of type 'Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl' to type 'Microsoft.AspNetCore.TestHost.TestServer'.)
If you put a breakpoint in the WebAppFixture constructor and try to step over the line where you assign the result of GetTestServer to _server you will get an unhandled exception
This is because you are using WebApplication.CreateBuilder()
instead of WebApplicationFactory<TEntrypoint>
. So if we check integration testing examples from microsoft for some examples and modify them slightly to accommodate your situation.
public class WebAppFixture : IDisposable
{
public readonly HttpClient TestServerClient;
public WebAppFixture()
{
TestServerClient = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
builder.ConfigureAppConfiguration((_, context) =>
{
//context.AddInMemoryCollection();
});
builder.ConfigureTestServices(services =>
{
//services.AddTransient<SomeService>();
});
builder.UseEnvironment("LOCAL_TEST");
}).CreateClient();
}
public void Dispose()
{
TestServerClient.Dispose();
}
}
Your test class is unchanged and you can test your implementation using _webAppFixture.TestServerClient
[Fact]
public async Task TestSomething()
{
var result = await _webAppFixture.TestServerClient.GetAsync("/WeatherForecast");
IEnumerable<WeatherForecast> autoParsedResult = await _webAppFixture.TestServerClient.GetFromJsonAsync<IEnumerable<WeatherForecast>>("/WeatherForecast");
Assert.Equal(System.Net.HttpStatusCode.OK, result.StatusCode);
Assert.Equal(5, autoParsedResult.Count());
}
Links you want to take a look at: