Using Environment Variables in .NET xUnit Tests
I want dotnet test
to handle environment variables. On *nix systems I should be able to type MyEnvVar=Hello dotnet test
and then be able to access that variable within my tests.
Creating a basic test
Create a new xUnit project and add our favorite assertion library Shouldly.
dotnet new xunit
dotnet add package Shouldly
Our first and only test will expect an IConfiguration
object to be injected at runtime and we’ll assert that our environment variable MyEnvVar
is set to Hello
.
using Microsoft.Extensions.Configuration;
using Xunit;
using Shouldly;
namespace MyTestProject
{
public class UnitTest1
{
public readonly IConfiguration _config;
public UnitTest1(IConfiguration config)
{
_config = config;
}
[Fact]
public void Test1()
{
_config.GetValue<string>("MyEnvVar").ShouldBe("Hello");
}
}
}
Injecting environment variables
The above test will fail because the IConfiguration
object is not available. Xunit.DependencyInjection lets us configure a Startup
similar to how we would in an AspNetCore web project.
dotnet add package Xunit.DependencyInjection
dotnet add package Microsoft.Extensions.Configuration.EnvironmentVariables
After adding the packages we add the Startup
class. Using ConfigureHost
within this class, we can call AddEnvironmentVariables
.
public class Startup
{
public void ConfigureHost(IHostBuilder hostBuilder)
{
var config = new ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
hostBuilder.ConfigureHostConfiguration(builder => builder.AddConfiguration(config));
}
}
Now when we run our test with MyEnvVar=Hello dotnet test
we get a passing result.
Debugging in VSCode
When we debug the test in Visual Studio Code the test still fails however. This is because we haven’t set the environment variable when debugging. To do so, add the following snippet to .vscode/settings.json
:
{
"csharp.unitTestDebuggingOptions": {
"env": {
"MyEnvVar": "Hello",
}
}
}
Debug the test and now it passes!
Conclusion
Xunit.DependencyInjection has not only given an easy way to access environment variables in our tests, but we’ve also got Dependency Injection (see ConfigureServices
) and, a sneaky way to perform global test setup tasks without the need for collection fixtures.