EnvironmentAbstractions 5.0.0
dotnet add package EnvironmentAbstractions --version 5.0.0
NuGet\Install-Package EnvironmentAbstractions -Version 5.0.0
<PackageReference Include="EnvironmentAbstractions" Version="5.0.0" />
paket add EnvironmentAbstractions --version 5.0.0
#r "nuget: EnvironmentAbstractions, 5.0.0"
// Install EnvironmentAbstractions as a Cake Addin #addin nuget:?package=EnvironmentAbstractions&version=5.0.0 // Install EnvironmentAbstractions as a Cake Tool #tool nuget:?package=EnvironmentAbstractions&version=5.0.0
EnvironmentAbstractions
The EnvironmentAbstractions
package provides an interface, IEnvironmentProvider
, that can be used as a layer of abstraction for code to be easier to mock for unit testing.
IEnvironmentProvider
The IEnvironmentProvider
interfaces supports the following members:
public interface IEnvironmentProvider : IEnvironmentVariableProvider
{
string CommandLine { get; }
string CurrentDirectory { get; set; }
int CurrentManagedThreadId { get; }
int ExitCode { get; }
bool HasShutdownStarted { get; }
bool Is64BitOperatingSystem { get; }
bool Is64BitProcess { get; }
string MachineName { get; }
string NewLine { get; }
OperatingSystem OSVersion { get; }
#if NET5_0_OR_GREATER
int ProcessId { get; }
#endif
int ProcessorCount { get; }
#if NET6_0_OR_GREATER
string? ProcessPath { get; }
#endif
string StackTrace { get; }
string SystemDirectory { get; }
int SystemPageSize { get; }
int TickCount { get; }
#if NETCOREAPP3_1_OR_GREATER
long TickCount64 { get; }
#endif
string UserDomainName { get; }
bool UserInteractive { get; }
string UserName { get; }
Version Version { get; }
long WorkingSet { get; }
void Exit(int exitCode);
void FailFast(string? message);
void FailFast(string? message, Exception? exception);
string? ExpandEnvironmentVariables(string name);
string? GetEnvironmentVariable(string name, EnvironmentVariableTarget target);
string? GetEnvironmentVariable(string name);
IReadOnlyDictionary<string, string> GetEnvironmentVariables();
IReadOnlyDictionary<string, string> GetEnvironmentVariables(EnvironmentVariableTarget target);
string[] GetCommandLineArgs();
string GetFolderPath(Environment.SpecialFolder folder);
string GetFolderPath(Environment.SpecialFolder folder, Environment.SpecialFolderOption option);
string[] GetLogicalDrives();
void SetEnvironmentVariable(string name, string? value);
void SetEnvironmentVariable(string name, string? value, EnvironmentVariableTarget target);
}
IEnvironmentVariableProvider
The IEnvironmentVariableProvider
interface is just for abstracting away access to environment variables and supports the following methods:
public interface IEnvironmentVariableProvider
{
string? ExpandEnvironmentVariables(string name);
string? GetEnvironmentVariable(string name, EnvironmentVariableTarget target);
string? GetEnvironmentVariable(string name);
IReadOnlyDictionary<string, string> GetEnvironmentVariables();
IReadOnlyDictionary<string, string> GetEnvironmentVariables(EnvironmentVariableTarget target);
void SetEnvironmentVariable(string name, string? value);
void SetEnvironmentVariable(string name, string? value, EnvironmentVariableTarget target);
}
Examples
The example below shows how to use IEnvironmentProvider
in a class to access the environment. You should have two constructors: one that does default logic
and another that accepts an IEnvironmentProvider
instance. The constructor that accepts an IEnvironmentProvider
can be internal so it can only be
called by unit tests.
public class MyClass
{
private readonly IEnvironmentProvider environmentProvider;
/// <summary>
/// Internal constructor only for unit tests which accesses the environment from the specified IEnvironmentProvider.
/// </summary>
internal MyClass(IEnvironmentProvider environmentProvider)
{
this.environmentProvider = environmentProvider
}
/// <summary>
/// Initializes a new instance of the MyClass class which accesses the environment directly from the system.
/// </summary>
public MyClass()
: this(SystemEnvironmentProvider.Instance)
{
}
public void SayHello()
{
// Get the current username from IEnvironmentProvider so that a test can mock the value
Console.WriteLine("Hello {0}!", environmentProvider.UserName);
}
public CustomConfig GetConfiguration()
{
// Check if the user has set an environment variable to override the default location
string customConfigLocation = environmentProvider.GetEnvironmentVariable("CUSTOM_CONFIG");
if (!string.IsNullOrWhitespace(environmentProvider))
{
return LoadConfigFromLocation(customConfigLocation);
}
// Load the configuration from the default location, %UserProfile%\configuration.xml
return LoadConfiguationFromLocation(Path.Combine(environmentProvider.GetEnvironmentVariable("USERPROFILE"), "configuration.xml"));
}
}
Alternatively, you can use the IEnvironmentVariableProvider
interface in a class to only abstract away access to environment variables. Like the example above, you should have two constructors: one that does default logic
and another that accepts an IEnvironmentVariableProvider
instance. The constructor that accepts an IEnvironmentVariableProvider
can be internal so it can only be
called by unit tests.
public class MyClass
{
private readonly IEnvironmentVariableProvider environmentVariableProvider;
/// <summary>
/// Internal constructor only for unit tests which reads environment variables from the specified IEnvironmentVariableProvider.
/// </summary>
internal MyClass(IEnvironmentVariableProvider environmentVariableProvider)
{
this.environmentVariableProvider = environmentVariableProvider
}
/// <summary>
/// Initializes a new instance of the MyClass class which reads environment variables directly from the system.
/// </summary>
public MyClass()
: this(SystemEnvironmentVariableProvider.Instance)
{
}
public CustomConfig GetConfiguration()
{
// Check if the user has set an environment variable to override the default location
string customConfigLocation = environmentVariableProvider.GetEnvironmentVariable("CUSTOM_CONFIG");
if (!string.IsNullOrWhitespace(environmentVariableProvider))
{
return LoadConfigFromLocation(customConfigLocation);
}
// Load the configuration from the default location, %UserProfile%\configuration.xml
return LoadConfiguationFromLocation(Path.Combine(environmentVariableProvider.GetEnvironmentVariable("USERPROFILE"), "configuration.xml"));
}
}
Unit tests can then use the MockEnvironmentProvider
or MockEnvironmentVariableProvider
class from the
EnvironmentAbstractions.TestHelpers package, an existing mocking framework like
Moq, or any custom implementation.
MockEnvironmentProvider
[Fact]
public void MethodReturnsExpectedValue()
{
IEnvironmentProvider environmentProvider = new MockEnvironmentProvider
{
// Initializes this instance to have the UserName property return "UserA"
UserName = "UserA",
};
// Sets an environment variable value
environmentProvider["Variable1"] = "Value1";
MyClass instance = new MyClass(environmentVariableProvider);
string actualUsername = instance.GetUserName();
Assert.Equal(actualUsername, "UserA");
}
MockEnvironmentVariableProvider
[Fact]
public void MethodReturnsExpectedValue()
{
IEnvironmentVariableProvider environmentVariableProvider = new MockEnvironmentVariableProvider
environmentVariableProvider["Variable1"] = "Value1";
MyClass instance = new MyClass(environmentVariableProvider);
string value = instance.Method();
}
Preventing usage of System.Environment
If you want to use IEnvironmentProvider
or IEnvironmentVariableProvider
exclusively in your repository, you can reference the
EnvironmentAbstractions.BannedApiAnalyzer package which uses the
Microsoft.CodeAnalysis.BannedApiAnalyzers
Roslyn analyzer to prevent code from accessing the System.Environment
APIs.
Sample project
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="EnvironmentAbstractions.BannedApiAnalyzer" Version="1.0.0" />
</ItemGroup>
</Project>
Sample source code
public static void Main(string[] args)
{
Console.WriteLine("Hello, {0}!", System.Environment.GetEnvironmentVariable("USERNAME"));
}
Sample error
warning RS0030: The symbol 'Environment.GetEnvironmentVariable(string)' is banned in this project: Use IEnvironmentVariableProvider.GetEnvironmentVariable(string) instead.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
-
net6.0
- No dependencies.
-
net8.0
- No dependencies.
-
net9.0
- No dependencies.
NuGet packages (3)
Showing the top 3 NuGet packages that depend on EnvironmentAbstractions:
Package | Downloads |
---|---|
EnvironmentAbstractions.TestHelpers
Provides implementations of IEnvironmentVariableProvider so that unit tests can mock calls that retrieve environment variable. |
|
EnvironmentAbstractions.BannedApiAnalyzer
Adds rules for Microsoft.CodeAnalysis.BannedApiAnalyzers to ensure projects don't use the System.Environment class to manipulate environment variables.. |
|
File.TestLogger
Provides a logger for the Visual Studio Test Platform that writes output to a file. |
GitHub repositories (2)
Showing the top 2 popular GitHub repositories that depend on EnvironmentAbstractions:
Repository | Stars |
---|---|
microsoft/slngen
Visual Studio solution generator
|
|
chickensoft-games/GameDemo
The Chickensoft Game Demo — a fully tested, third-person 3D game built with Godot and C#. Now with saving and loading!
|