【问题标题】:ASP.NET Core 3.1 - WebApplicationFactory - What is the correct usage for WebApplicationFactoryContentRootAttribute?ASP.NET Core 3.1 - WebApplicationFactory - WebApplicationFactoryContentRootAttribute 的正确用法是什么?
【发布时间】:2020-12-19 05:55:24
【问题描述】:

我正在学习如何在 ASP.NET Core 3.1 中使用 WebApplicationFactory。特别是我想弄清楚WebApplicationFactoryContentRoot的正确用法

我创建了一个示例 Github 存储库来演示我遇到的问题。

我正在尝试使用 WebApplicationFactoryContentRoot 属性为 ../../../Src/WebApp 的启动引导类设置内容根。

当我为下面的代码运行 dotnet test 时,它似乎没有引用 WebApplicationFactoryContentRootAttribute 设置。

抛出System.IO.DirectoryNotFoundException:'my solution base dir'/WebApp。

路径应该是“我的解决方案基础目录”/Src/WebApp

如何让派生的WebApplicationFactory 识别WebApplicationFactoryContentRootAttribute

集成测试

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;
        }
    }
}

测试项目

<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>

【问题讨论】:

  • 查看文章How the test infrastructure infers the app content root path 了解 WebApplicationFactory 如何推断应用内容根路径。使用自定义 WebApplicationFactory 时,我们可以使用以下代码指出 Web 应用程序内容根的正确位置:var client = _factory.WithWebHostBuilder(builder =&gt;builder.UseSolutionRelativeContentRoot("relative/path/of/project/under/test")).CreateClient();
  • @zhi-lv 谢谢,非常感谢 :) 试过了,它可以在本地开发环境中工作。但是,我似乎无法让 UseSolutionRelativeContentRoot 在 docker 容器环境中工作。我创建了一个小的GitHub repository 来突出我遇到的问题。仍然不确定为什么WebApplicationFactoryContentRootAttribute 没有效果????

标签: c# asp.net-core .net-core


【解决方案1】:

问题可能是您的文件引用是 Program.cs,而它应该是另一个程序集的 DLL(即 WebApp.dll) - 因为在您的 Docker 容器 中不会有任何基于构建输出的*.cs 文件。

在测试项目中(在您已有的测试文件中,或者在AssemblyInfo.cs 中,如果有多个测试文件):

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

在你的测试课中:

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

其中Startup 是您正在测试的MyNamespace.AssemblyName 项目中的类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-04
    • 2021-05-02
    • 2022-07-23
    • 2020-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多