如何在 .net6 中使用 WebApplicationFactory(没有可说话的入口点)

How to use WebApplicationFactory in .net6 (without speakable entry point)

在ASP.NET中,Core 6默认模板将Sturtup.cs中的所有内容移动到Program.cs中,并在Program.cs中使用顶级语句,所以没有更多(可说的) Program class 以太币。

这看起来很棒,但现在,我需要测试所有这些。 WebApplicationFactory<T> 仍然希望我通过入口点-class,但我不能这样做(因为它的名字现在无法表达)。

如何在 ASP.NET Core 6 中配置集成测试?

问题已在 ASP.NET Core RC1 上解决,但截至目前(2021 年 9 月 20 日)文档尚不完整。

编译器在后台生成一个 Program class 可以与 WebApplicationFactory<> 一起使用。 class 不是 public,所以应该使用 InternalsVisibleTo 项目设置。

Damien Edwards' Minimal API sample uses the latest nightly bits。测试网络应用 class 声明为:

internal class PlaygroundApplication : WebApplicationFactory<Program>
{
    private readonly string _environment;

    public PlaygroundApplication(string environment = "Development")
    {
        _environment = environment;
    }

    protected override IHost CreateHost(IHostBuilder builder)
    {
    ...

在应用项目文件中,InternalsVisibleTo用于使Programclass对测试项目可见:

  <ItemGroup>
    <InternalsVisibleTo Include="MinimalApiPlayground.Tests" />
  </ItemGroup>

RC1 功能齐全,从以前的主要版本来看,它可能是第一个拥有 Go Live 许可证的版本,这意味着它在生产中得到支持。

请注意,如果您尝试使用 xUnit 及其 IClassFixture<T> 模式,如果您只使用 InternalsVisibleTo 方法,您将 运行 遇到问题。具体来说,你会得到这样的东西:

“不一致的可访问性:基本 class WebApplicationFactory<Program> 比 class CustomWebApplicationFactory 更难访问。”

当然,您可以通过将 CustomWebApplicationFactory 设置为内部来解决此问题,但它只会移动问题,因为现在您的单元测试 class 将给出相同的错误。当您尝试在那里更改它时,您会发现 xUnit 要求测试具有 public 构造函数(不是内部构造函数),您将被阻止。

避免所有这些并允许您仍然使用 IClassFixture<Program> 的解决方案是使 Program class public。您显然可以通过删除 Program.cs 的魔术 no class 版本来做到这一点,但是如果您不想完全更改该文件,您可以只添加以下行:

public partial class Program { } // so you can reference it from tests

当然,一旦它 public 您就可以在您的测试项目中使用它,并且一切正常。

顺便说一句,您通常更喜欢使用 IClassFixture 的原因是它允许您在测试 class 构造函数中仅设置一次 WebApplicationFactory,并获取一个 HttpClient 实例您可以从中存储为一个字段。这允许您的所有测试更短,因为它们只需要引用客户端实例,而不是工厂。

示例:

public class HomePage_Get : IClassFixture<CustomWebApplicationFactory>
{
    private readonly HttpClient _client = new HttpClient();

    public HomePage_Get(CustomWebApplicationFactory factory)
    {
        _client = factory.CreateClient();
    }
    [Fact]
    public async Task IncludesWelcome()
    {
        HttpResponseMessage response = await _client.GetAsync("/");
        response.EnsureSuccessStatusCode();
        string stringResponse = await response.Content.ReadAsStringAsync();
        Assert.Contains("Welcome.", stringResponse);
    }
}

最后注意Damian Edwards' MinimalAPIPlayground was updated to use this approach after we discussed the issue. See this commit

我试过了

 <InternalsVisibleTo Include="MinimalApiPlayground.Tests" />

但是没有雪茄!删除它并添加部分 class 到 program.cs

#pragma warning disable CA1050 // Declare types in namespaces
public partial class Program
{
}
#pragma warning restore CA1050 // Declare types in namespaces

效果惊人。