【问题标题】:Can a profile from the launchSettings.json file be loaded when running unit tests?运行单元测试时可以加载 launchSettings.json 文件中的配置文件吗?
【发布时间】:2018-12-05 17:47:04
【问题描述】:

我正在运行单元测试作为 ASP.NET Core MVC 解决方案的一部分。 .NET Core 的版本准确地说是 2.1。

我在 launchSettings.json 文件中创建了一个配置文件部分,其中包含我希望由测试运行程序加载和注入的环境变量,以便环境变量可用并且在运行单元测试时可以包含特定值。

我的 ASP.NET Core MVC 项目中的 launchSettings.json 作为链接添加到我的单元测试项目中,并且属性设置为构建操作 - 无,复制到输出文件夹 - 始终复制。

该文件被复制到我的输出文件夹,但我不确定如何让测试运行程序将此文件与 UnitTesting 配置文件一起使用。我尝试使用“测试”一词作为配置文件名称,但似乎没有任何效果。

这是一个示例 launchSettings.json 文件:

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:62267/",
      "sslPort": 0
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "MigrationHistoryTableName": "MigrationHistory",
        "ConnectionStringName": "EFConnectionString",
        "Redis__SSL": "True",
        "Redis__Port": "6380",
        "Redis__InstanceName": "RedisDev",
        "Redis__AbortConnect": "False",
        "Redis__ConnectionString": "{URI}:{Port},password={Password},ssl={SSL},abortConnect={AbortConnect}"
      }
    },
    "MyDataServices": {
      "commandName": "Project",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "MigrationHistoryTableName": "MigrationHistory",
        "ConnectionStringName": "EFConnectionString",
        "Redis__SSL": "True",
        "Redis__Port": "6380",
        "Redis__InstanceName": "RedisDev",
        "Redis__AbortConnect": "False",
        "Redis__ConnectionString": "{URI}:{Port},password={Password},ssl={SSL},abortConnect={AbortConnect}"
      },
      "applicationUrl": "http://localhost:4080/"
    },
    "UnitTesting": {
      "commandName": "Executable",
      "executablePath": "test",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "MigrationHistoryTableName": "MigrationHistory",
        "ConnectionStringName": "EFConnectionString",
        "Redis__SSL": "True",
        "Redis__Port": "6380",
        "Redis__InstanceName": "RedisDev",
        "Redis__AbortConnect": "False",
        "Redis__ConnectionString": "{URI}:{Port},password={Password},ssl={SSL},abortConnect={AbortConnect}"
      }
    }
  }
}

我了解默认情况下,git 中会忽略 launchSettings.json 文件。我们将使用此文件的开发版本签入我们的代码,该文件将包含预期在开发环境中可用的设置示例。

感谢您抽出宝贵时间阅读本文并提供帮助!

【问题讨论】:

  • 目前,我创建了一个从文件加载配置文件并将环境变量设置为测试设置夹具的一部分的方法,但如果它,我宁愿让框架为我做这件事是可能的。
  • 你想获取具体的 UnitTesting 配置文件吗?
  • 是的,那太棒了。

标签: c# asp.net-core .net-core


【解决方案1】:

我现在写了这个静态加载器,但这并不理想:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace MyNamespaceHere.Services.Common.Utilities
{
    public static class LaunchSettingsLoader
    {
        public static void LaunchSettingsFixture(string launchSettingsPath = "Properties\\launchSettings.json", string profileName = "UnitTesting")
        {
            using (var file = File.OpenText(launchSettingsPath))
            {
                var reader = new JsonTextReader(file);
                var jObject = JObject.Load(reader);

                var allprofiles = jObject
                    .GetValue("profiles", StringComparison.OrdinalIgnoreCase);

                // ideally we use this
                var variables = jObject
                    .GetValue("profiles", StringComparison.OrdinalIgnoreCase)
                    //select a proper profile here
                    .SelectMany(profiles => profiles.Children())
                    //.Where(p => p.Value<String> == profileName)
                    .SelectMany(profile => profile.Children<JProperty>())
                    .Where(prop => prop.Name == "environmentVariables")
                    .SelectMany(prop => prop.Value.Children<JProperty>())
                    .ToList();

                Console.WriteLine(variables?.Count);

                var profilesDictJToken = allprofiles.ToObject<Dictionary<string, JToken>>();
                var unitTestingProfile = profilesDictJToken[profileName];
                var unitTestingProfileDictJToken = unitTestingProfile.ToObject<Dictionary<string, JToken>>();
                var environmentVariables = unitTestingProfileDictJToken["environmentVariables"];
                var environmentVariablesList = environmentVariables.ToList();

                foreach (var variable in environmentVariablesList)
                {
                    var name = ((JProperty)variable).Name;
                    var value = ((JProperty)variable).Value.ToString();
                    Environment.SetEnvironmentVariable(name, value);
                }
            }
        }
    }
}

【讨论】:

  • 您是否设法获取当前的 profileName?我有类似的场景,但我需要在运行时获取 profileName
  • 我的第一次尝试是使用上面的 JsonTextReader 和我从另一篇文章中找到的以 var variables = jObject... 行开头的代码块,但它会遍历所有配置文件。在底部附近使用字典的效率较低的代码允许我将其缩小到一个配置文件,该配置文件的名称通过 profileName 变量传递。
  • 是的,但是您如何知道您是使用“UnitTesting”配置文件还是“OtherProfile”运行?我的意思是,你如何获得当前的运行配置文件
  • 我没有,我使用 .json 文件的路径和我想用于单元测试运行的配置文件名称显式调用该方法,因为我不知道如何获得测试runner 自动使用 launchSettings.json 文件。
  • 更好的解决方案是完全使用环境变量而不是设置文件。这种方法在容器化您的解决方案时非常有效。在设计时,您将创建一个包含实际设置值的 .env 文件,并将该文件从源代码管理中排除。您可以在源代码控制下提供带有建议设置的 Sample.env 文件(当然没有秘密)。对于您的单元测试,您可以从文件中加载环境变量值,或者在安排测试时明确定义它们。见nuget.org/packages/DotNetEnv
【解决方案2】:

对于 mstest 或 xunittest,在单元测试中使用环境变量的另一种解决方案是通过为平台提供的 ".runsettings" 文件:

请看下面的链接:

https://stackoverflow.com/a/68531200/4593944

【讨论】:

    【解决方案3】:

    我创建了一个包,也许可以帮助你:https://www.nuget.org/packages/DotNet.Project.LaunchSettings

    您可以在这里找到来源:https://github.com/andygjp/DotNet.Project.LaunchSettings

    我有一个与您类似的用例 - 我想测试不同的环境,并将这些环境的登录详细信息保存在 launchSettings.json 中。

    我就是这样使用它的:

    async Task Example()
    {
      var launchSettings = VisualStudioLaunchSettings.FromCaller();
      var profiles = launchSettings.GetProfiles();
      var profile = profiles.FirstOrEmpty();
    
      var client = await AppEnvironment.FromEnvironment(profile.EnvironmentVariables).CreateClient();
      // use the client
    }
    

    假设 launchSettings.json 在通常的位置:

    MyProject -> 属性 -> launchSettings.json

    但是,如果您觉得有用的话,我可以添加从指定文件路径加载启动设置的功能。

    上面的示例使用它找到的第一个配置文件,但是,您也可以使用特定的配置文件。

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-28
      • 2015-10-25
      • 1970-01-01
      相关资源
      最近更新 更多