AppSettings.json 用于 ASP.NET Core 中的集成测试

Posted

技术标签:

【中文标题】AppSettings.json 用于 ASP.NET Core 中的集成测试【英文标题】:AppSettings.json for Integration Test in ASP.NET Core 【发布时间】:2017-05-13 23:19:56 【问题描述】:

我正在关注这个guide。我在使用appsettings.json 配置文件的API 项目中有一个Startup

public class Startup

    public Startup(IHostingEnvironment env)
    
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)                
            .AddEnvironmentVariables();
        Configuration = builder.Build();

        Log.Logger = new LoggerConfiguration()
            .Enrich.FromLogContext()
            .ReadFrom.Configuration(Configuration)
            .CreateLogger();
    

我正在查看的特定部分是env.ContentRootPath。我做了一些挖掘,看起来我的appsettings.json 实际上并没有复制到bin 文件夹,但这很好,因为ContentRootPath 正在返回MySolution\src\MyProject.Api\,这是appsettings.json 文件所在的位置。

所以在我的集成测试项目中我有这个测试:

public class TestShould

    private readonly TestServer _server;
    private readonly HttpClient _client;

    public TestShould()
    
        _server = new TestServer(new WebHostBuilder().UseStartup<Startup>());
        _client = _server.CreateClient();
    

    [Fact]
    public async Task ReturnSuccessful()
    
        var response = await _client.GetAsync("/monitoring/test");
        response.EnsureSuccessStatusCode();

        var responseString = await response.Content.ReadAsStringAsync();

        Assert.Equal("Successful", responseString);
    

这基本上是从指南中复制和粘贴。当我调试这个测试时,ContentRootPath 实际上是MySolution\src\MyProject.IntegrationTests\bin\Debug\net461\,这显然是测试项目的构建输出文件夹,appsettings.json 文件也不存在(是的,我在测试项目中有另一个appsettings.json 文件本身),因此测试在创建 TestServer 时失败。

我尝试通过修改测试project.json 文件来解决这个问题。

"buildOptions": 
    "emitEntryPoint": true,
    "copyToOutput": 
        "includeFiles": [
            "appsettings.json"
       ]
    

我希望这会将 appsettings.json 文件复制到构建输出目录,但它抱怨项目缺少入口点的 Main 方法,将测试项目视为控制台项目。

我能做些什么来解决这个问题?我做错了吗?

【问题讨论】:

【参考方案1】:

删除测试project.json文件中的"emitEntryPoint": true

【讨论】:

这消除了关于它缺少Main 的错误,但它没有将appsettings.json 复制到bin 目录中。【参考方案2】:

最后,我关注了这个guide,特别是页面底部的集成测试部分。这消除了将appsettings.json 文件复制到输出目录的需要。相反,它会告诉测试项目 Web 应用程序的实际目录。

至于将appsettings.json 复制到输出目录,我也设法让它工作。结合 dudu 的回答,我使用了 include 而不是 includeFiles,所以生成的部分看起来像这样:

"buildOptions": 
    "copyToOutput": 
        "include": "appsettings.json"
    

我不完全确定为什么会这样,但确实如此。我快速浏览了文档,但找不到任何真正的差异,并且由于最初的问题已经基本解决,所以我没有进一步查看。

【讨论】:

据我了解:在测试期间,当您使用目标应用程序根目录作为内容根目录和/或基本路径(而不是测试输出目录)时,您的应用程序Startup 将使用自己的@987654328 @,就像在测试之外运行时一样。在这种情况下,将测试项目appsettings.json 复制到其输出目录将无效。根本不会读取该 json 文件。这是你的经历吗? 如何在 .NET.Core 2.0 中做到这一点? project.json 已弃用。 嗨@Kevin Lee 你能指定你使用的实际代码而不是指向指南吗?有时微软会在过去两年更改文档,谢谢【参考方案3】:

集成测试ASP.NET.Core 2.0上关注MS guide,

您应该右键单击appsettings.json 将其属性Copy to Output directory 设置为始终复制

现在您可以在输出文件夹中找到 json 文件,并使用

构建 TestServer
var projectDir = GetProjectPath("", typeof(TStartup).GetTypeInfo().Assembly);
_server = new TestServer(new WebHostBuilder()
    .UseEnvironment("Development")
    .UseContentRoot(projectDir)
    .UseConfiguration(new ConfigurationBuilder()
        .SetBasePath(projectDir)
        .AddJsonFile("appsettings.json")
        .Build()
    )
    .UseStartup<TestStartup>());



/// Ref: https://***.com/a/52136848/3634867
/// <summary>
/// Gets the full path to the target project that we wish to test
/// </summary>
/// <param name="projectRelativePath">
/// The parent directory of the target project.
/// e.g. src, samples, test, or test/Websites
/// </param>
/// <param name="startupAssembly">The target project's assembly.</param>
/// <returns>The full path to the target project.</returns>
private static string GetProjectPath(string projectRelativePath, Assembly startupAssembly)

    // Get name of the target project which we want to test
    var projectName = startupAssembly.GetName().Name;

    // Get currently executing test project path
    var applicationBasePath = System.AppContext.BaseDirectory;

    // Find the path to the target project
    var directoryInfo = new DirectoryInfo(applicationBasePath);
    do
    
        directoryInfo = directoryInfo.Parent;

        var projectDirectoryInfo = new DirectoryInfo(Path.Combine(directoryInfo.FullName, projectRelativePath));
        if (projectDirectoryInfo.Exists)
        
            var projectFileInfo = new FileInfo(Path.Combine(projectDirectoryInfo.FullName, projectName, $"projectName.csproj"));
            if (projectFileInfo.Exists)
            
                return Path.Combine(projectDirectoryInfo.FullName, projectName);
            
        
    
    while (directoryInfo.Parent != null);

    throw new Exception($"Project root could not be located using the application root applicationBasePath.");

参考:TestServer w/ WebHostBuilder doesn't read appsettings.json on ASP.NET Core 2.0, but it worked on 1.1

【讨论】:

嗨@John_J 你也能帮忙回答这个问题吗?谢谢,***.com/questions/57318131/… 嗨@John_J ProjectDir 是什么?它是实际项目的路径,还是实际项目构建工件的路径,比如 bin-debug 类型的文件夹?请在回答中指定,谢谢 - 另外,如果您正在测试,如何指向原始应用程序启动? GetCurrentDirectory 是测试项目的目录,不是真正的项目吗? 嗨@JeremyWatkins,contentRoot 是您的 .csproj 文件所在的位置。我使用 ***.com/a/52136848/3634867 的“GetProjectPath” @user11721944 ,作为方法描述,ProjectDir 是“获取我们希望测试的目标项目的完整路径”而不是测试项目目录。试试看吧:)

以上是关于AppSettings.json 用于 ASP.NET Core 中的集成测试的主要内容,如果未能解决你的问题,请参考以下文章

[三] ASP.NET Core配置文件

.NET Core 应用程序中的 appsettings.json 与 appsettings.Environment.json

用 appsettings.Production.json 中的设置覆盖 appsettings.json 中的数组设置

appsettings.json 和 runtimeconfig.json 有啥区别?

读取 appsettings.json

使用 appsettings.json 配置 Serilog RollingFile