简体   繁体   中英

ASP.NET Core 3.1 - WebApplicationFactory - What is the correct usage for WebApplicationFactoryContentRootAttribute?

I am learning how to use the WebApplicationFactory in ASP.NET Core 3.1. In particular I am trying to figure out the correct usage of WebApplicationFactoryContentRoot

I have created a sample Github repository to demonstrate the issues that I am encountering.

I am trying to use WebApplicationFactoryContentRoot attribute to set the content root for a Startup bootstrap class at ../../../Src/WebApp .

When I run dotnet test for the code below it does not appear to be referencing the WebApplicationFactoryContentRootAttribute settings.

A System.IO.DirectoryNotFoundException is thrown : 'my solution base dir'/WebApp.

The path should be 'my solution base dir'/Src/WebApp

How do I get the derived WebApplicationFactory to recognise the WebApplicationFactoryContentRootAttribute

Integration Test

using System.IO;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

using Autofac.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Mvc.Testing;
using Xunit;
using Xunit.Abstractions;

using WebApp;
using WebApp.S3.Contracts;
using WebApp.Functional.Utilities;


/// Key should match FullName of assembly containing TStartup : WebApplicationFactory<TStartup> 
/// https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.testing.webapplicationfactorycontentrootattribute?view=aspnetcore-3.0
[assembly: WebApplicationFactoryContentRootAttribute(
    "WebApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
    "../../../Src/WebApp",
    "Program.cs",
    "1")]


namespace WebApp.FunctionalTests
{
    /// <summary>
    /// Eventual Goal: Tryng to create WebApplicationFactory with content root at Src/WebApp using
    /// appsettings file derived from ASPNETCORE_ENVIRONMENT variable. If
    /// the variable is unset then defaults to appsettings.Local.json
    /// </summary>
    public class AppTestFixture : WebApplicationFactory<Startup>
    {
        //override methods here as needed for Test purpose
    }


    public class ApiIntegrationTest : IClassFixture<AppTestFixture>
    {
        private WebApplicationFactory<Startup> _factory;
        private ITestOutputHelper _output;


        /// <summary>
        /// Initialise derived WebApplicationFactory and output stream
        /// </summary>
        /// <param name="factory"><see cref="AppTestFixture"/>, dervied WebApplicationFactory</param>
        /// <param name="output">xUnit output stream</param>
        public ApiIntegrationTest(AppTestFixture factory, ITestOutputHelper output)
        {
            const string contentRoot = "Src/WebApp";

            _factory = factory;
            _output = output;

            // sanity check for FullName property of assembly containing Startup class
            string fullName = Assembly.GetAssembly(typeof(Startup)).FullName;
            _output.WriteLine($"FullName property of assembly containing 'Startup' class => {fullName}");
        }

        /// <summary>
        /// /Users/me/Development/dotnet/blazormotiondetectionlistener/WebApp/ not found
        ///
        /// Should be path /Users/me/Development/dotnet/blazormotiondetectionlistener/Src/WebApp/
        /// </summary>
        ///
        /// <remarks>
        /// How do I use WebApplicationFactoryContentRoot attribute to correctly resolve this?
        /// </remarks>
        [Fact]
        public async Task WebApp_App_ApiController_Test()
        {
            var client = _factory.CreateClient();

            await Task.CompletedTask;
        }
    }
}

Test project

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>

    <IsPackable>false</IsPackable>
  </PropertyGroup>

  <ItemGroup>
    <Content Update="xunit.runner.json">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Autofac" Version="6.0.0" />
    <PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
    <PackageReference Include="xunit" Version="2.4.1" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
    <PackageReference Include="coverlet.collector" Version="1.0.1" />
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\..\..\Src\WebApp\WebApp.csproj" />
    <ProjectReference Include="..\..\Functional\Utilities\WebApp.Functional.Utilities.csproj" />
    <ProjectReference Include="..\..\..\Src\WebApp.S3.Contracts\WebApp.S3.Contracts.csproj" />
  </ItemGroup>

</Project>

The issue may be that your file reference is Program.cs when it should be the DLL of the other assembly (ie, WebApp.dll ) - because in your Docker Container there won't be any *.cs files if it is based on build output.

In the test project (either in your test file as you already have it, or in AssemblyInfo.cs if there are multiple test files):

[assembly: WebApplicationFactoryContentRoot("MyNamespace.AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "./", "MyNamespace.AssemblyName.dll", "1")]

In your test class:

private readonly WebApplicationFactory<Startup> applicationFactory = new();

Where Startup is the class in your MyNamespace.AssemblyName project under test.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM