【问题标题】:F#: How to avoid "[FS0988] Main module of program is empty: nothing will happen when it is run" in Tests Project?F#:如何避免Tests项目出现“[FS0988]程序主模块为空:运行时什么都不会发生”?
【发布时间】:2026-01-11 03:25:02
【问题描述】:

我有一个包含以下项目的 .NET 解决方案:

  • Console:控制台.NET Core 2.2
  • Domain:.NET 标准 2.0
  • Domain.Tests:控制台 .NET Core 2.2 (XUnit)
  • Infrastructure:.NET 标准 2.0

我的Domain.Tests.fsproj 定义为:

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

    <PropertyGroup>

        <IsPackable>false</IsPackable>
        <GenerateProgramFile>false</GenerateProgramFile>
        <TargetFramework>netcoreapp2.2</TargetFramework>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="FsCheck" Version="3.0.0-alpha4" />
        <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
        <PackageReference Include="xunit" Version="2.4.0" />
        <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
    </ItemGroup>

    <ItemGroup>
      <Compile Include="Dsl.fs" />
      <Compile Include="OpenAccountTests.fs" />
      <Compile Include="CloseAccountTests.fs" />
      <Compile Include="DepositCashTests.fs" />
      <Compile Include="WithdrawCashTests.fs" />
      <Compile Include="WireMoneyTests.fs" />
      <Compile Include="RequestAddressChangeTests.fs" />
      <Compile Include="RequestEmailChangeTests.fs" />
      <Compile Include="RequestPhoneNumberChangeTests.fs" />
      <Compile Include="ValidateAddressChangeTests.fs" />
      <Compile Include="ValidateEmailChangeTests.fs" />
      <Compile Include="ValidatePhoneNumberChangeTests.fs" />
    </ItemGroup>

    <ItemGroup>
      <ProjectReference Include="..\Domain\Domain.fsproj" />
    </ItemGroup>

</Project>

但是在编译解决方案时,我有以下警告:

ValidatePhoneNumberChangeTests.fs(102, 35): [FS0988] 程序主模块为空:运行时什么都不会发生

我检查了that answer on SO 并在Domain.Tests 的最后一个文件的末尾添加do()ValidatePhoneNumberChangeTests.fs 没有做任何事情。

我能做些什么来消除这个警告?

【问题讨论】:

    标签: compilation f# compiler-warnings


    【解决方案1】:

    @rmunn 在 cmets 中处于正确的轨道上。当TargetFrameworknetstandardXXnet4XX&lt;OutputType&gt; 默认为Library,当TargetFrameworknetcoreappXXExe

    设置 &lt;OutputType&gt;Library&lt;/OutputType&gt; 是 IMO 解决此问题的最佳方法,而不是添加不会被调用的入口点。

    【讨论】:

    • 话虽如此,如果我改用 Library + .NET Standard,Rider 将不再运行单元测试 =/(所以归根结底,这可能更像是 Rider 问题)
    • 我刚刚遇到了这个确切的问题,似乎添加 Library 可以解决这个问题,但它没有。
    【解决方案2】:
    <TargetFramework>netcoreapp2.2</TargetFramework>
    

    这将 Domain.Tests 项目指定为可执行文件

    如果你只需要它是一个类库,那就把它改成

    <TargetFramework>netstandard2.0</TargetFramework>
    

    如果您只是想删除警告,您可以通过在 ValidatePhoneNumberChangeTests.fs 的末尾添加此方法或在编译顺序末尾的 Program.fs 中添加一个 main 方法

    [<EntryPoint>] 
    let main argv =
        0
    

    【讨论】:

    • 它必须是 &lt;TargetFramework&gt;netcoreapp2.2&lt;/TargetFramework&gt; 才能运行测试(至少这是我在 Rider 中的经验)
    • 在这种情况下,您可以通过在 ValidatePhoneNumberChangeTests.fs 的末尾添加此方法或在编译顺序末尾的 Program.fs 中添加此方法来伪造 main 方法 [] let main argv = 0
    • Program.fs 在编译顺序的末尾加上[&lt;EntryPoint&gt;] let main argv = 0 成功了谢谢!
    • 我认为是 &lt;OutputType&gt; 属性将项目指定为可执行文件或类库。根据docs.microsoft.com/en-us/visualstudio/msbuild/…,它默认为Library,但我看到了多个堆栈溢出问题,询问为什么在没有&lt;OutputType&gt; 的情况下MSBuild 正在构建exe 而不是dll,所以也许可以尝试将&lt;OutputType&gt;Library&lt;/OutputType&gt; 添加到您的. fsproj 看看有什么作用? (如果是这样,您将需要删除 Program.fs 文件,因为 DLL 中不需要该文件)。
    【解决方案3】:

    只需删除 Program.fs 和 OutputType(它对我也不起作用)。像这样在 PropertyGroup 中将 GenerateProgramFile 设置为 true:

    <PropertyGroup>
        <TargetFramework>net5.0</TargetFramework>
        <IsPackable>false</IsPackable>
        <GenerateProgramFile>true</GenerateProgramFile>
    </PropertyGroup>
    

    干杯!

    【讨论】:

      最近更新 更多