Static dependencies cause a lot of problems with code testability. They’re hard to mock, and if tests change static values and don’t clean up after themselves, it can cause other tests to unexpectedly fail.
A common static dependency in .NET (before .NET Core’s rethinking of how configuration should work, anyway) is appSettings values from .config files.
Unit tests can code test values, e.g.:
ConfigurationManager.AppSettings["key"] = "test value";
…but as mentioned above, they have to undo overrides to make sure they don’t affect other tests.
AppSettingsHelper
This class lets you test with one or more appSettings overrides and automatically roll back the overrides when the test is complete.:
using SparkyTestHelpers.AppSettings
...
AppSettingsHelper
.WithAppSetting("bar", "test bar value")
.AndAppSetting("baz", "test baz value")
.Test(() =>
{
// Code to test method that uses "bar" & "baz"
// ConfigurationManager.AppSettings values
});
The WithAppSetting clause is required. You can use zero or as many additional AndAppSetting overrides as you need. The .Test method “calls back” to a test Action that uses the ConfigurationManager.AppSettings value(s).
But there’s a better way...
AppSettings.TestDependencyProvider
Code with static dependencies can be made more testable by using a dependency-injectable wrapper around the static code. SparkyTools.DependencyProvider provides one way to do this.
The SparkyTools.XmlConfig NuGet package has an AppSettings.DependencyProvider() method that creates a DependencyProvider wrapping ConfigurationManager.AppSettings.
This (SparkyTestHelpers.AppSettings) package has an AppSettings.TestDependencyProvider() method that creates a provider that serves test values from a key/value dictionary:
Class using appSettings, made testable via DependencyProvider:
using SparkyTools.DependencyProvider;
public class Foo
{
private readonly Func<string, string> _getAppSetting;
public Foo(DependencyProvider<Func<string, string>> appSettingsProvider)
{
_getAppSetting = appSettingsProvider.GetValue();
}
public void MethodUsingAppSettings()
{
string bar = _getAppSetting("bar");
string baz = _getAppSetting("baz");
}
}
Code using “real” DependencyProvider that wraps ConfigurationManager.AppSettings:
using SparkyTools.XmlConfig;
...
var foo = new Foo(AppSettings.DependencyProvider());
Unit test code using dictionary DependencyProvider:
using SparkyTestHelpers.AppSettings;
...
var provider = AppSettings.DependencyProvider(
new Dictionary<string, string>
{
{ "bar", "test bar value" },
{ "baz", "test baz value" }
});
var foo = new Foo(provider);
Happy Testing!
Top comments (0)