0

I am trying to run a test for my project that will need the whole API app to run by using process to start and run the application on a real TCP socket for eventual pact testing.

The API seems to start but my test fails to connect to the local host.

My test sets up the Process in a StartProcess class and uses dotnet run within the API app directory to run the app:

public class GetWeatherForecastTest
{
    private Process StartProcess()
    {
        var processStartInfo = new ProcessStartInfo
        {
            FileName = "dotnet",
            Arguments = "run",
            WorkingDirectory = "../../../../ProcessAPI",
            RedirectStandardOutput = true,
            UseShellExecute = false,
            CreateNoWindow = true
        };

        var process = new Process { StartInfo = processStartInfo };
        process.OutputDataReceived += (sender, args) => Debug.WriteLine(args.Data);
        process.ErrorDataReceived += (sender, args) => Debug.WriteLine(args.Data);
        process.Start();
        process.BeginOutputReadLine();
        process.BeginErrorReadLine();

        return process;
    }

    [Fact]
    public async Task GivenValidParameters_WhenGetWeatherForecast_ThenReturnForecast()
    {
        using (var process = StartProcess())
        {
            // Wait for the process to start and the server to be ready
            await Task.Delay(5000);

            using (var client = new HttpClient())
            {
                try
                {
                    var response = await client.GetAsync("http://localhost:5083/WeatherForecast");
                    response.EnsureSuccessStatusCode();

                    var responseString = await response.Content.ReadAsStringAsync();
                    Assert.False(string.IsNullOrEmpty(responseString));

                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"Request error: {ex.Message}");
                    throw;
                }

                process.Kill();
            }
        }
    }
}

The error response I get when running this test shows that the connection is refused.

[xUnit.net 00:00:09.25]       System.Net.Http.HttpRequestException : No connection could be made because the target machine actively refused it. (localhost:5000)
[xUnit.net 00:00:09.25]       ---- System.Net.Sockets.SocketException : No connection could be made because the target machine actively refused it.
[xUnit.net 00:00:09.25]       Stack Trace:
[xUnit.net 00:00:09.25]            at System.Net.Http.HttpConnectionPool.ConnectToTcpHostAsync(String host, Int32 port, HttpRequestMessage initialRequest, Boolean async, CancellationToken cancellationToken)
[xUnit.net 00:00:09.25]            at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
[xUnit.net 00:00:09.25]            at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
[xUnit.net 00:00:09.25]            at System.Net.Http.HttpConnectionPool.InjectNewHttp11ConnectionAsync(QueueItem queueItem)
[xUnit.net 00:00:09.25]            at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
[xUnit.net 00:00:09.25]            at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
[xUnit.net 00:00:09.25]            at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
[xUnit.net 00:00:09.25]            at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
[xUnit.net 00:00:09.25]         C:\Programming\ProcessAPI\ProcessAPI.Test\GetWeatherForecastTest.cs(33,0): at ProcessAPI.Test.GetWeatherForecastTest.GivenValidParameters_WhenGetWeatherForecast_ThenReturnForecast()

So the app does appear to start but the test is unable to connect to the locally running server.

8
  • 1
    Are you sure the server has actually started? that the delay is long enough? and that there where no errors? Does the server works when started manually and tested with a webbrowser? Commented Mar 28 at 9:11
  • @JonasH when running the test it sets up the port but then doesn't dispose of it when the test fails. This means the build fails the next time I run the test or build so I need to manually kill the task that's running the port. Commented Mar 28 at 9:34
  • So are you asking how to shutdown the server nicely? Or maybe take the port as an parameter so you can select a free port each time? I'm not sure what the actual question is. Commented Mar 28 at 9:38
  • 1
    You don't use dotnet run to start another process, you only use it during development to compile and start your project. When you build or publish your project with dotnet build or dotnet publish you get an .exe file you can call directly. Commented Mar 28 at 9:47
  • 1
    What's the actual question anyway? How to write integration tests for a Web API project? That's explained in Integration tests in ASP.NET Core. Instead of trying to manually start the web app, your test class should inherit from IClassFixture<WebApplicationFactory<Program>>. This will set up a test web host and ensure it runs before your tests are called. In those tests, _factory.CreateClient(); is used to retrieve an HttpClient instance that talks to the test server Commented Mar 28 at 9:50

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.