.net 如何从测试项目的debug文件夹中测试自包含的exe?

cnwbcb6i  于 2023-04-13  发布在  .NET
关注(0)|答案(1)|浏览(89)

尝试从xunit项目的调试文件夹启动exe时出错。

A fatal error was encountered. The library 'hostpolicy.dll' required to execute the application was not found in 'C:\Program Files\dotnet\'.
Failed to run as a self-contained app.
  - The application was run as a self-contained app because 'C:\Users\me\Desktop\dotnet-testing-cli-issue\MyApp.Console.Tests\bin\Debug\net7.0\MyApp.Console.runtimeconfig.json' did not specify a framework.
  - If this should be a framework-dependent app, specify the appropriate framework in 'C:\Users\me\Desktop\dotnet-testing-cli-issue\MyApp.Console.Tests\bin\Debug\net7.0\MyApp.Console.runtimeconfig.json'.

MyApp.Console.csproj:

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

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <RuntimeIdentifier>win-x64</RuntimeIdentifier>
  </PropertyGroup>

</Project>

Program.cs

// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");

MyApp.Console.Tests.csproj

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

  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>

    <IsPackable>false</IsPackable>
    <IsTestProject>true</IsTestProject>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="CliWrap" Version="3.6.0" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
    <PackageReference Include="xunit" Version="2.4.2" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\MyApp.Console\MyApp.Console.csproj" />
  </ItemGroup>

</Project>

Tests.cs

public class UnitTest1
{
    [Fact]
    public async Task Test1Async()
    {
        var result = await Cli.Wrap("MyApp.Console.exe")
            .WithArguments(new[] { "--foo", "bar" })
            .ExecuteAsync();
    }
}

完整复制:https://github.com/VictorioBerra/netcore-console-test-exe
这也可能是一个X-Y问题。我想测试我的控制台应用程序,包括一个使用通用主机的应用程序,即appsettings。
如何启动并测试它?

vhmi4jdf

vhmi4jdf1#

如果您构建解决方案并打开“MyApp.Console.Tests\bin\Debug\net7.0”和“MyApp.Console.Tests\bin\Debug\net7.0”文件夹并比较内容,您将看到后者的文件比前者多得多-这些文件是自包含应用附带的运行时的一部分,并且需要运行它。您可以设置一些精心设计的构建操作来执行正确的应用程序发布到某个路径,并在测试项目中使用它,但我认为这太复杂,而且可能太脆弱。
您可以切换到“旧”Program.Main样式(如果项目是使用dotnet new console CLI命令创建的-提供--use-program-main,因此无需手动更改),运行Program.Main(args),然后通过Console.Out捕获“当前”控制台输出:

public sealed class ConsoleCapture : IDisposable
{
    private readonly StringWriter _stringWriter = new();

    private readonly TextWriter _oldOut;
    private readonly TextWriter _oldErr;

    public ConsoleCapture()
    {
        _oldOut = Console.Out;
        _oldErr = Console.Error;

        Console.SetOut(_stringWriter);
        Console.SetError(_stringWriter);
    }

    public string GetAll()
    {
        return _stringWriter.ToString();
    }

    public void Dispose()
    {
        Console.SetOut(_oldOut);
        Console.SetError(_oldErr);

        _stringWriter.Dispose();
    }
}

和用法:

using var console = new ConsoleCapture();
var res = Program.Main(args);

var consoleOutput = console.GetAll();

Assert.AreEqual(expectedExitCode, res);
Assert.Contains("Hello World", res);

打开PR并举例说明。

备注

  • 对于ASP .NETCore应用程序,使用集成测试方法-see this answer for some details(并且不需要上面的所有内容)更容易。
  • 如果您仍然希望保留顶层语句Program文件,那么您可以执行一些反射来调用生成的Program.<Main>$,尽管这会更脆弱一些,因为生成模式可能会改变(尽管有一个选项可以通过使用Assembly.EntryPoint来缓解这种情况-请参见this answer)。
  • 至于配置-请注意,内置configuration in .NET支持多个提供程序并使用分层方法。您可以在测试项目中复制(或从主项目添加as a link)appsettings文件(尽管通常您会有一个独立的)和/或提供配置作为CLI参数(some examples here

相关问题