Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a profile from the launchSettings.json file be loaded when running unit tests?

I am running unit tests as part of an ASP.NET Core MVC solution. The version of .NET Core is 2.1 to be exact.

I have created a profile section in a launchSettings.json file that contains environment variables that I would like to have loaded and injected by the test runner, so that the environment variables are available and can contain specific values when running unit tests.

The launchSettings.json from my ASP.NET Core MVC project is added to my unit test project as a link, and the properties are set to Build Action - None, Copy to output folder - Copy Always.

The file gets copied to my output folder, but I'm not sure how to get the test runner to use this file with the UnitTesting profile. I have tried using the word "Test" as the profile name, nothing seems to work.

Here is a sample launchSettings.json file:

{
  "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}"
      }
    }
  }
}

I understand that by default the launchSettings.json file is ignored in git. We will check in our code with a development version of this file that will contain an example of the settings that are expected to be available in a development environment.

Thank you kindly for taking the time to read this and help out!

like image 533
Yves Rochon Avatar asked Dec 05 '18 17:12

Yves Rochon


1 Answers

I wrote this static loader for now, but that's not ideal:

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);
                }
            }
        }
    }
}
like image 86
Yves Rochon Avatar answered Oct 04 '22 09:10

Yves Rochon