Running xUnit tests on Teamcity using asynchronous methods

I performed the following xUnit test, which uses the HttpClient to call the state api method on the web server.

[Fact] public void AmIAliveTest() { var server = TestServer.Create<Startup>(); var httpClient = server.HttpClient; var response = httpClient.GetAsync("/api/status").Result; response.StatusCode.Should().Be(HttpStatusCode.OK); var resultString = response.Content.ReadAsAsync<string>().Result; resultString.Should().Be("I am alive!"); } 

This test works fine locally. But when I pass the code and try to run the same test on the TeamCity build server, it works forever. I even need to kill the xunit runner process because stopping the build will not stop this process.

However, when I write a test like this

 [Fact] public async void AmIAliveTest() { var server = TestServer.Create<Startup>(); var httpClient = server.HttpClient; var response = await httpClient.GetAsync("/api/status"); response.StatusCode.Should().Be(HttpStatusCode.OK); var resultString = await response.Content.ReadAsAsync<string>(); resultString.Should().Be("I am alive!"); } 

It works great locally as well as in TeamCity.

Now I'm worried that I forgot to write a test as a second option, and from time to time the teamcity build hangs.

Can someone explain to me why xUnit running on the teamcity build server does not run the test correctly in the first place? And is there a solution for this to solve this?

+2
source share
2 answers

Can someone explain to me why xUnit running on the teamcity build server does not run the test correctly in the first place?

First, I would check your xUnit versions - you have to run the recently released 2.0. I suspect your local version may be outdated.

The main problem is this line:

 var resultString = response.Content.ReadAsAsync<string>().Result; 

I suspect that you are faced with a deadlock situation that I describe on my blog. HttpClient has some methods on some platforms that use ConfigureAwait(false) incorrectly and therefore are subject to this deadlock. xUnit 2.0 installs a single-threaded SynchronizationContext in all of its unit tests, which provides the second half of the deadlock script.

The correct solution is to replace Result with await and change the return type of your unit test method from void to Task .

+6
source

Your tests are broken.

xUnit needs to return Task to understand that the test failed, and more to the point, this is a handle in which the exception returns to xUnit.

By having a public async void , you have lost the orphanhood of Task . An exceptional exception, of course, is not handled, and of course, therefore, it blows up the whole process. Therefore, your test run stops.

You can fix this by writing all your tests like this ...

 [Fact] public async Task AmIAliveTest() { var server = TestServer.Create<Startup>(); var httpClient = server.HttpClient; var response = await httpClient.GetAsync("/api/status"); response.StatusCode.Should().Be(HttpStatusCode.OK); var resultString = await response.Content.ReadAsAsync<string>(); resultString.Should().Be("I am alive!"); } 
-2
source

Source: https://habr.com/ru/post/1013005/


All Articles