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.
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 run 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:
- Constructor
- Base class
- Fixture
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.
launchsettings.json
to setup test environment. Instead we create a single simplified json key-value file. It's shared as link for all integration test projects in solution. If you need to keep multiple environments/profiles, consider a config transform like it is done for appsettings.json
in ASP.NET Core. –
Crazy launchSettings.json
to be observed by dotnet test
, then you can take that up with VSTest, since they're perfectly welcome to add that feature in a framework-independent way, which makes more sense that asking each individual framework to do it. –
Freeze 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.
- Add a file with .runsettings extension in the project:
- Configure environment variables in file "xxx.runsettings" created:
<!-- File name extension must be .runsettings --> <RunSettings> <RunConfiguration> <EnvironmentVariables> <!-- List of environment variables we want to set--> <VARIABLE_XXXX>value X</VARIABLE_XXXX> <VARIABLE_YYYY>value Y</VARIABLE_YYYY> </EnvironmentVariables> </RunConfiguration> </RunSettings>
- 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.
Another options to use .runsettings are in link below:
Great thread helped me find the adapted solution for me. I needed something that works well for local dev / tests (using VS code) JSON file works fine. I also needed something that can be used with CI/CD and deployment; environment variables were needed. My fixture class needs the environment variable to be able to run the tests in the different environments.
I'm using the same principle @Ilya Chumakov except with System.Text.Json (in 2022 using .NET 6...) I thought that sharing it might help save other people some time:
if (File.Exists(Directory.GetCurrentDirectory()+"/local.settings.json")){
using var file = File.Open(Directory.GetCurrentDirectory()+ "/local.settings.json",FileMode.Open);
var document = JsonDocument.Parse(file);
var variables = document.RootElement.EnumerateObject();
foreach(var variable in variables){
Environment.SetEnvironmentVariable(variable.Name, variable.Value.ToString());
}
}
All the needed variables are at the root of the local.settings.json. adapt if you use it for a lot of things, easy to add an "env"
property which contains all your environment variable and just read from it.
For those who use VS code like me. Don't forget to add to your .csproj:
<ItemGroup>
<Content Include="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
Took me also a bit of tinkering to find that out.
© 2022 - 2024 — McMap. All rights reserved.