有没有办法在 C# 中对顶级语句进行单元测试?

Is there a way to unit test top-level statements in C#?

我一直在摆弄顶级语句作为简单控制台应用程序的入口点,因为新的 .NET 6 模板默认使用它们。

然而,正如 language specification 非常清楚地指出:

Note that the names "Program" and "Main" are used only for illustrations purposes, actual names used by compiler are implementation dependent and neither the type, nor the method can be referenced by name from source code.

所以,如果我不能引用隐式的Program class和它的Main()方法,是否可以编写单元测试来检查top的执行流程级语句本身?如果可以,怎么做?

是的。一种选择(自 .NET 6 起)是使测试项目的内部结构对测试项目可见,例如通过将 next 属性 添加到 csproj:

<ItemGroup>
  <InternalsVisibleTo Include ="YourTestProjectName"/>
</ItemGroup>

然后为顶级语句生成的 Program class 应该对测试项目可见,您可以 运行 接下来的方式:

var entryPoint = typeof(Program).Assembly.EntryPoint!;
entryPoint.Invoke(null, new object[] { Array.Empty<string>() }); 

类似这样的东西在内部用于以最小的托管模型为 执行集成测试。

请注意,如果您在顶级语句中使用 await,则 generated Main 方法可以 return 执行任务,因此您可能需要捕获 return 的 entryPoint.Invoke 并测试它是否是 Taskawait

另一种方法是显式声明 Program class 为部分(例如在顶级语句的末尾并在测试项目中使用它):

// ...
// your top-level statements

public partial class Program { }