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

Posted

技术标签:

【中文标题】如何在 .net6 中使用 WebApplicationFactory(没有可说的入口点)【英文标题】:How to use WebApplicationFactory in .net6 (without speakable entry point) 【发布时间】:2021-09-04 18:55:15 【问题描述】:

在 ASP.NET Core 6 中,默认模板将所有内容从 Sturtup.cs 移动到 Program.cs,并使用 Program.cs 中的***语句,因此不再有(可说的)Program 类 ether。

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

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

【问题讨论】:

您需要将服务设置提取到扩展方法中,然后在测试项目中创建一个启动类并调用这些扩展方法。现在您可以使用WebApplicationFactory<TStartup>,而无需在应用项目中使用。 @abdusco 听起来像个黑客。这样我就不会在Program.cs 中看到我的大部分配置(我认为这是将Startup 移动到那里的意图)。您的建议是或多或少地创建一个新的Sturtup。但是感谢您的解决方法,这至少是使其正常工作的某种方式。 @abdusco 等等,但我仍然需要提供一些 TStartup,不是吗? 您可以随时将扩展类/启动类放在 Program.cs 中。不管不引入抽象,如何指定 Program.cs 中的哪些行属于应用程序配置?好吧,您将应用程序设置提取到一个类中并为其命名,稍后您可以在测试项目中引用它,这正是 Startup 类的用途。最小化 API 很酷,但它的命令性使得目前有些事情变得困难。 【参考方案1】:

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

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

Damien Edwards' Minimal API sample 使用the latest nightly bits。测试网络应用程序类声明为:

internal class PlaygroundApplication : WebApplicationFactory<Program>

    private readonly string _environment;

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

    protected override IHost CreateHost(IHostBuilder builder)
    
    ...

在应用程序项目文件中,InternalsVisibleTo 用于使Program 类对测试项目可见:

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

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

【讨论】:

感谢您的提示,这确实有效,但是将 InternalsVisibleTo 添加到 api 项目中:github.com/dotnet/AspNetCore.Docs/issues/… 您能否将其添加到答案中?花了一些时间弄清楚为什么使用 Program 会失败。 @МаксимКошевой 谢谢,我添加了这个【参考方案2】:

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

“不一致的可访问性:基类 WebApplicationFactory&lt;Program&gt; 的可访问性低于类 CustomWebApplicationFactory。”

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

避免所有这些并允许您仍然使用IClassFixture&lt;Program&gt; 的解决方案是将Program 类公开。您显然可以通过摆脱神奇的无类版本 Program.cs 来做到这一点,但如果您不想完全更改该文件,您可以添加以下行:

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

当然,一旦公开,您就可以在测试项目中使用它,一切正常。

顺便说一句,您通常更喜欢使用 IClassFixture 的原因是它允许您在测试类构造函数中设置一次 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 已更新为使用此方法。看到这个commit

【讨论】:

听起来像是一种解决方法.. 哦,确实是这样。 public partial class Program 为我工作,我不必使用InternalsVisibleTo 公开内部类型。以下是提到使用WebApplicationFactory 进行测试但没有Startup 类的文档的链接:docs.microsoft.com/en-us/aspnet/core/test/…【参考方案3】:

我试过了

 <InternalsVisibleTo Include="MinimalApiPlayground.Tests" />

但没有雪茄!将其删除并在 program.cs 中添加了一个部分类

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


#pragma warning restore CA1050 // Declare types in namespaces

效果惊人。

【讨论】:

这很奇怪 InternalsVisibleTo 为我工作(并继续在 .Net 6 rc2 中工作)。你的Program 类是public,所以这个问题可能是你错误地添加了InternalsVisibleTo。也许您的测试项目的名称不是MinimalApiPlayground.Tests 嗨@maxc137,我确实更改了名称,但是,我使用了“ABC”中的名称而不是.Tests(大概是一个命名空间),有趣的是我会再试一次,我不是当然,但我认为我更喜欢在启动时,因为现在更容易记住两次被这个抓住了!

以上是关于如何在 .net6 中使用 WebApplicationFactory(没有可说的入口点)的主要内容,如果未能解决你的问题,请参考以下文章

收集.NET6中一些常用组件的配置

收集.NET6中一些常用组件的配置

收集.NET6中一些常用组件的配置

收集.NET6中一些常用组件的配置

如何在 Azure DevOps 中为 .net6 iOS 应用程序配置配置文件?

如何在 .NET 6.0 中使用 MinimalApi 配置 NewtonsoftJson