Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>For your example, the first thing I'd do is to create an interface exposing the functionality you need to read config e.g.</p> <pre><code>public interface IConfigReader { string GetAppSetting(string key); ... } </code></pre> <p>and then create an implementation which delegates to the static ConfigurationManager class:</p> <pre><code>public class StaticConfigReader : IConfigReader { public string Get(string key) { return ConfigurationManager.AppSetting[key]; } } </code></pre> <p>Then for a particular class with a dependency on the configuration you can create a seam which initially just returns an instance of the static config reader:</p> <pre><code>public class ClassRequiringConfig { public void MethodUsingConfig() { string setting = this.GetConfigReader().GetAppSetting("key"); } protected virtual IConfigReader GetConfigReader() { return new StaticConfigReader(); } } </code></pre> <p>And replace all references to ConfigManager with usages of your interface. Then for testing purposes you can subclass this class and override the GetConfigReader method to inject fakes so you don't need any actual config file:</p> <pre><code>public class TestClassRequiringConfig : ClassRequiringConfig { public IConfigReader ConfigReader { get; set; } protected override IConfigReader GetConfigReader() { return this.ConfigReader; } } [Test] public void TestMethodUsingConfig() { ClassRequiringConfig sut = new TestClassRequiringConfig { ConfigReader = fakeConfigReader }; sut.MethodUsingConfig(); //Assertions } </code></pre> <p>Then eventually you will be able to replace this with property/constructor injection when you add an IoC container.</p> <p>EDIT: If you're not happy with injecting instances into individual classes like this (which would be quite tedious if many classes depend on configuration) then you could create a static configuration class, and then allow temporary changes to the config reader for testing:</p> <pre><code> public static class Configuration { private static Func&lt;IConfigReader&gt; _configReaderFunc = () =&gt; new StaticConfigReader; public static Func&lt;IConfigReader&gt; GetConfiguration { get { return _configReaderFunc; } } public static IDisposable CreateConfigScope(IConfigReader reader) { return new ConfigReaderScope(() =&gt; reader); } private class ConfigReaderScope : IDisposable { private readonly Func&lt;IConfigReader&gt; _oldReaderFunc; public ConfigReaderScope(Func&lt;IConfigReader&gt; newReaderFunc) { this._oldReaderFunc = _configReaderFunc; _configReaderFunc = newReaderFunc; } public void Dispose() { _configReaderFunc = this._oldReaderFunc; } } } </code></pre> <p>Then your classes just access the config through the static class:</p> <pre><code>public void MethodUsingConfig() { string value = Configuration.GetConfigReader().GetAppSetting("key"); } </code></pre> <p>and your tests can use a fake through a temporary scope:</p> <pre><code>[Test] public void TestMethodUsingConfig() { using(var scope = Configuration.CreateConfigScope(fakeReader)) { new ClassUsingConfig().MethodUsingConfig(); //Assertions } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload