Reputation: 73
I have a Web-API .NET Core 2.2 project and I am trying to do integration tests on it.
I have followed the guide from Microsoft. The tests pass when starting them from the test runner and from the command line, they should be configured correctly, I am able to call the controllers via the WebApplicationFactory - HTTP client. I have disabled shadow copy via xunit.runner.json So far so good.
I am trying to use Azure DevOps to deploy my project and at the release step, I've added a test step that takes the build artifact, downloads it and runs the test. Basically, replicated on the local machine, this would translate into:
dotnet publish testProject.csproj <path_on_disk>
cd <path_on_disk>
vstest.console.exe testProject.dll
When running the tests from a published folder, I get the following error
Failed wInvoiceIntegrationTests.Controllers.Authentication.AuthenticationControllerTests.AuthenticationController_Register_InputDoesNotRespectsModel_DoesNotRegistersUser(email: "abcd@@.com", password: "Abcdefgh1")
Error Message:
System.InvalidOperationException : Solution root could not be located using application root C:\Users\mihai\Desktop\publish\.
Stack Trace:
at Microsoft.AspNetCore.TestHost.WebHostBuilderExtensions.UseSolutionRelativeContentRoot(IWebHostBuilder builder, String solutionRelativePath, String applicationBasePath, String solutionName)
at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.SetContentRoot(IWebHostBuilder builder)
at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.EnsureServer()
at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateDefaultClient(DelegatingHandler[] handlers)
at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateClient(WebApplicationFactoryClientOptions options)
I have no static files that I need to serve nor do I want to, I am just trying to test the controller. The path is correct, that's where the test dlls are and the project dlls are also included.
In the meantime I've managed to get the tests to run on azure, at the build stage via
ls *Tests*/*.csproj | xargs -L1 dotnet test --logger:trx
Any ideas on how to overcome this and run the tests from the publish folder?
Edit: Basically running the tests from the command line in the output directory and from the VS test explorer is ok, but running from the publish directory is not ok.
Upvotes: 6
Views: 5502
Reputation: 640
We ran into this problem and spent several hours piecing together the issue. Turns out both Jahan Afshari and Namig Hajiyev's solutions are relevant. I want to try to piece together their solutions into one whole.
First, check out the article referenced by Jahan and make sure it is relevant to you. If you are using .NET 5+, you definitely need to ensure that your code is initializing things the way that is outlined in that article.
If, however, that turns out not to be adequate to fix your problem, you'll need to make sure you've got things set up pretty much the way Namig did.
It turns out that his theory about just creating a dummy .sln file, however, is wrong. The .NET testing architecture isn't just looking for the presence of a .sln file. It is actually using the data in that file to find the path to the project holding the SUT code behind the mock Web Service interface that it is creating.
I loaded and stepped through the code behind the .NET assembly. It starts from the working directory and goes up the directory tree one parent at a time until it finds a directory with one or more .sln files. It then goes through each of those files looking for the path to the project with the SUT code in it.
Furthermore, although the nature of the .NET code would seem to indicate that the .sln file just needs to be in the directory path of the test project you are trying to run, it actually needs to be in the test project's immediate parent directory. If it is any further up the chain than that, you will run into another error in which it tries to reference the test project as if it were one directory below the solution file.
So bottom line: To get the .NET Web Service Test infrastructure to work, your Test Project that is creating a mock Web Service must have a solution in its parent directory that contains references both to the Test Project and to the SUT project with the code behind the Mock Web Service.
To be sure it will work, you should open up any other solution that contains all of the projects that your SUT project could depend on, run a Clean All, then close that solution, open the solution in your test project's parent directory, and run Build All from that solution. This will ensure that your build is not succeeding because other assemblies it depends on just happen to be prebuilt and sitting in your test project's build directory.
Once that solution is in place, you should be able to build and run your Test Project from any other solution you like. Just be aware that the Test Project code itself needs that solution in its parent directory to find and use the SUT code.
Upvotes: 2
Reputation: 109
I was getting the same error in my integration test project while using .NET Core 5.0. This solution fixed the problem for me: https://anthonygiretti.com/2021/04/16/testserver-asp-net-core-5-fix-system-invalidoperationexception-solution-root-could-not-be-located-using-application-root-with-a-custom-startup-file/.
You would first have to upgrade your project to .NET Core 5.0, of course.
Upvotes: 2
Reputation: 1541
Please see this part of the article https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2#how-the-test-infrastructure-infers-the-app-content-root-path-1
As you can see WebApplicationFactory class needs to infer the content root path. WebApplicationFactory finds the path from WebApplicationFactoryContentRootAttribute if defined. If that attribute is not found then solution (.sln) file is searched, the folder containing solution file is set to be the content root path. It seems neither you define WebApplicationFactoryContentRootAttribute in your test project nor the parent directory of the directory containing published dlls (testProject.dll) contains a .sln file.
As workaround just before running tests I copied sln file from my project into the parent folder of "publish" folder. I guess just creating dummy sln file could help as well. I run my test command from the parent directory like this :
dotnet test ./<publish folder>/testProject.dll
Note ./ is the parent directory where sln file is copied an "publish folder" is "path_on_disk" in your example
In my case after this additional errors came up showing missing directory. I have just created empty directory with exact name in the parent directory and it fixed the errors. Hope this could help you as well.
Upvotes: 6