代码之家  ›  专栏  ›  技术社区  ›  Victorio Berra

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

  •  0
  • Victorio Berra  · 技术社区  · 3 年前

    尝试从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'.
    

    我的应用程序控制台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>
    

    程序.cs

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

    我的应用程序控制台测试存储项目

    <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>
    

    测试s.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问题。我想测试我的控制台应用程序,包括一个使用通用主机的应用程序,应用程序设置,等等。

    我如何启动和测试它?

    0 回复  |  直到 3 年前
        1
  •  1
  •   Guru Stron    3 年前

    如果您要构建解决方案并打开“MyApp.Console.Tests\bin\Debug\net7.0”和“MyApp.coonsole.Ttests\bin\Degug\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.NET Core应用程序,使用集成测试方法更容易- see this answer for some details (不需要上面的所有内容)
    • 如果您仍然希望保留顶级语句 Program 文件,然后可以进行一些反射以调用生成的 Program.<Main>$ ,尽管这会有点脆弱,因为生成模式可能会发生变化(尽管可以通过使用 Assembly.EntryPoint -参见 this answer )。
    • 至于内置的配置说明 configuration in .NET 支持多个提供者并使用分层方法。你可以复制(或添加 as a link 来自主项目)和/或提供config作为CLI参数( some examples here )
    推荐文章