Should GetEnvironmentVariable Work in xUnit Test?

Visual Studio.Net CoreVisual Studio-2017xunit.net

Visual Studio Problem Overview


If I set environment variables for a .Net Core web project in Visual Studio 2017 using the project properties page, I can read the value of the variable using Environment.GetEnvironmentVariable; however, when I set the environment variable for my xUnit testing project and then debug the test, Environment.GetEnvironmentVariable always returns null. Is there something about the fact that it is a testing project that should prevent the variable from being used the same as with the web project? If so, is there a way that I can set the environment variables for a test project? Thank you.

Visual Studio Solutions


Solution 1 - Visual Studio

The GetEnvironmentVariable works fine in xUnit tests. The problem is to properly set a variable. If you set the variable at Properties -> Debug page, then the variable is written to Properties\launchSettings.json and Visual Studio makes all work to launch an application with the selected profile. As you could see, launchSettings.json even isn't copied to output folder by default. It's impossible to pass this file as argument to dotnet run or dotnet test, that leads to obvious problem if tests are runned automatically on a CI server. So it is not surprising that launchSettings.json isn't considered by a test runner.

Solution: there are a lot of ways to setup a test environment in xUnit:

For example, this collection fixture sets up all environment variables from launchSettings.json:

public class LaunchSettingsFixture : IDisposable
{
    public LaunchSettingsFixture()
    {
        using (var file = File.OpenText("Properties\\launchSettings.json"))
        {
            var reader = new JsonTextReader(file);
            var jObject = JObject.Load(reader);

            var variables = jObject
                .GetValue("profiles")
                //select a proper profile here
                .SelectMany(profiles => profiles.Children())
                .SelectMany(profile => profile.Children<JProperty>())
                .Where(prop => prop.Name == "environmentVariables")
                .SelectMany(prop => prop.Value.Children<JProperty>())
                .ToList();

            foreach (var variable in variables)
            {
                Environment.SetEnvironmentVariable(variable.Name, variable.Value.ToString());
            }
        }
    }

    public void Dispose()
    {
        // ... clean up
    }
}

Set Copy to output directory: Always for launchSettings.json to make the file accessible from tests.

Solution 2 - Visual Studio

A solution for using environment variables in unit tests, for either mstest or xunittest, is through the ".runsettings" file provided for the platform:

UPDATE: This works only for mstest.

  1. Add a file with .runsettings extension in the project:

Project Structure

  1. Configure environment variables in file "xxx.runsettings" created:

> > > > > > > value X > value Y > > >

  1. Add RunSettingsFilePath tag in test .csproj pointing to the .runsettings file.

> Important: the path is absolute. > > Using $(MSBuildProjectDirectory) variable will return the absolute path to the project diretory.

enter image description here

Another options to use .runsettings are in link below:

> https://docs.microsoft.com/pt-br/visualstudio/test/configure-unit-tests-by-using-a-dot-runsettings-file?view=vs-2019

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEricView Question on Stackoverflow
Solution 1 - Visual StudioIlya ChumakovView Answer on Stackoverflow
Solution 2 - Visual StudioDaniel ReisView Answer on Stackoverflow