Integration Tests using XUnit.NET - Solution root could not be located using application root

Viewed 1017

I have two projects in the solution.

  1. Web API using .NET Core 3.1
  2. Integration Tests using XUnit.NET and .NET Core 3.1, this project has a reference to Web API project

A sample integration test class is here.

public class CustomersControllerTests : IClassFixture<WebApplicationFactory<WebAPIProject.Startup>> 
    {
            public CustomersControllerTests(WebApplicationFactory<WebAPIProject.Startup> factory)
            {
                _httpClient = factory.CreateClient();
                _customerRepository = factory.Services.GetService<ICustomerRepository>();            
            }
    }

I developed the integration tests using the following article.

https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-3.1

All tests ran fine in Visual Studio. So the integration tests project is put into a Azure DevOps pipeline.

Here are the tasks in the Agent job.

  1. Download Pipeline Artifacts task (to download the build artifacts from build pipeline)
  2. Visual Studio test platfrom installer task
  3. Visual Studio Test task

All tests are failed during execution and here is the stack trace for one of the tests.

System.InvalidOperationException : Solution root could not be located using application root D:\a\r1\a\_ReleaseManagement.API.IntegrationTests-CI\drop\ReleaseManagement.IntegrationTests\Release\.
[xUnit.net 00:00:06.59]       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>b__20_0(IWebHostBuilder webHostBuilder)
at Microsoft.Extensions.Hosting.GenericHostWebHostBuilderExtensions.ConfigureWebHost(IHostBuilder builder, Action`1 configure)
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.CreateDefaultClient(Uri baseAddress, DelegatingHandler[] handlers)
at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateClient(WebApplicationFactoryClientOptions options)
at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateClient()
/home/vsts/work/1/s/src/UnitTests/ReleaseManagement.IntegrationTests/Api/CustomersControllerTests.cs(29,0): at ReleaseManagement.IntegrationTests.Api.CustomersControllerTests..ctor(WebApplicationFactory`1 factory)
2020-11-27T09:54:43.4381123Z ##[error][xUnit.net 00:00:06.59]     ReleaseManagement.IntegrationTests.Api.CustomersControllerTests.CreateCustomer_Success [FAIL]

Build pipeline definition -

steps:
 - task: UseDotNet@2
   displayName: "Use .NET Core SDK $(netCoreVersion)"
   inputs:
    version: $(netCoreVersion)


 - task: DotNetCoreCLI@2
   displayName: 'Restore project dependencies'
   inputs:
    command: 'restore'
    projects: '**/ABC.IntegrationTests/ABC.IntegrationTests.csproj'


 - task: DotNetCoreCLI@2
   displayName: 'Build API Integration Tests - $(buildConfiguration)'
   inputs:
    command: 'build'
    arguments: '--configuration $(buildConfiguration) --no-restore --output $(Build.ArtifactStagingDirectory)\ABC.IntegrationTests\Release'
    projects: '**/ABC.IntegrationTests/ABC.IntegrationTests.csproj'


 - task: PublishBuildArtifacts@1
   displayName: 'Publish build artifact: drop'
   condition: succeeded()

Release pipeline definition -

steps:
- task: DotNetCoreCLI@2
  displayName: 'dotnet test'
  inputs:
    command: test
    arguments: '_ABC.API.IntegrationTests-CI\drop\ABC.IntegrationTests\Release\ABC.IntegrationTests.dll'

Any help on how to resolve this issue so the tests can be executed in azure devops pipeline?

3 Answers

Basically "WebApplicationFactory" needs "WebApplicationFactoryContentRootAttribute" to find the root so read more here.

Try this fix or maybe this one

According to the error log, in the process of dotnet test, it needs to refer to the source files of the build. But when it does not exist on the machine, it will fail.

/home/vsts/work/1/s/src/UnitTests/ReleaseManagement.IntegrationTests/Api/CustomersControllerTests.cs(29,0): at ReleaseManagement.IntegrationTests.Api.CustomersControllerTests..ctor(WebApplicationFactory`1 factory)

To solve this issue, you could try the following methods:

1.Integrate build and test in the Same build pipeline.

enter image description here

  1. If you want to split build and test in different pipelines, you need to pay attention to the following points.
  • You need to make sure that the build and release pipeline are using the same Microsoft-hosted Agents. (From your log, they are using the different kind of agents)

  • You need to add the repo source in release pipeline. Then Add the copy file task and dotnet restore task in the Release pipeline.

Release Artifacts:

enter image description here

Release Task

enter image description here

Explanation:

The copy file task is used to copy file source to the build agent sourcedirectory path. You could check the Specific path in the release error log.

For example: Build sourcepath: D:\a\1\s Release Pipeline Copy the file to D:\a\1\s

The dotnet restore task is used to restore the source file required packages. In dotnet test, it could require some packages.

3.You could create a Self-hosted agent. Then you could directly run the build and test on the self-hosted agent without Additional settings.

I have made the following changes to resolve the posted issues.

  1. Copy the MainSolution.sln file to the Release build / publish folder
  2. Created a CustomWebApplicationRepository as below

public class CustomWebApplicationFactory : WebApplicationFactory<WebAPIProject.Startup> {

protected override void ConfigureWebHost(IWebHostBuilder builder)
{
    builder.UseContentRoot(AppContext.BaseDirectory);
    base.ConfigureWebHost(builder);
    
}

}

  1. Use the CustomWebApplicationFactory in the integration tests.

    public class CustomersControllerTests : IClassFixture<CustomWebApplicationFactory> { public CustomersControllerTests(CustomWebApplicationFactory factory) { _httpClient = factory.CreateClient(); _customerRepository = factory.Services.GetService();
    } }

Related