Unit Testable Configuration Manager

If you are a TDD purist, you should know that accessing file system in Unit Test is violating the rule. But in our application, our infrastructural code often requires to access the configuration values form web.config/app.config. In this post, I will show you how can create a simple wrapper class which you can use in your unit tests without hitting the file system.

First, create a interface which will allow us to access the common sections of the configuration file:

01 public interface IConfigurationManager
02 {
03 NameValueCollection AppSettings
04 {
05 get;
06 }
07
08 string ConnectionStrings(string name);
09
10 T GetSection<T>(string sectionName);
11 }

Next, the implementation:

01 using System.Collections.Specialized;
02 using System.Configuration;
03
04 public class ConfigurationManagerWrapper : IConfigurationManager
05 {
06 public NameValueCollection AppSettings
07 {
08 get
09 {
10 return ConfigurationManager.AppSettings;
11 }
12 }
13
14 public string ConnectionStrings(string name)
15 {
16 return ConfigurationManager.ConnectionStrings[name].ConnectionString;
17 }
18
19 public T GetSection<T>(string sectionName)
20 {
21 return (T) ConfigurationManager.GetSection(sectionName);
22 }
23 }

This is a very common pattern which you will find all over in the new ASP.NET 3.5 SP1 System.Web.Abstraction. The rule is whatever thing is not unit testable, create an interface with the exact same signature and create a wrapper class which internally calls the corresponding method/property.

Now lets say, we would like to do some processing with some configuration values like the following (By the way the Process() is a poor example):

01 public void Process()
02 {
03 string appVersion = _configuration.AppSettings["version"];
04 string connectionString = _configuration.ConnectionStrings("myDatabase");
05
06 OutputCacheSettingsSection settings = _configuration.GetSection<OutputCacheSettingsSection>("system.web/caching/outputCacheSettings");
07 int duration = 0;
08
09 if (settings.OutputCacheProfiles.Count > 0)
10 {
11 OutputCacheProfile profile = settings.OutputCacheProfiles.Get("MyProfile");
12
13 if (profile != null)
14 {
15 duration = profile.Duration;
16 }
17 }
18
19 //Now perform operation with these values;
20 }

Now, we can write the unit test like the following which does not requires the web.config/app.config file:

01 [Fact]
02 public void Test_Process()
03 {
04 _configuration.Expect(c => c.AppSettings).Returns(new NameValueCollection{ { "version", "1.0" } });
05 _configuration.Expect(c => c.ConnectionStrings(It.IsAny<string>())).Returns(@"Data Source=.\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True");
06
07 OutputCacheProfile cacheProfile = new OutputCacheProfile("MyProfile") { Duration = 360 };
08 OutputCacheSettingsSection cacheSection = new OutputCacheSettingsSection();
09 cacheSection.OutputCacheProfiles.Add(cacheProfile);
10
11 _configuration.Expect(c => c.GetSection<OutputCacheSettingsSection>(It.IsAny<string>())).Returns(cacheSection);
12
13 _processor.Process();
14 }

Enjoy!!!

About eagle081183

Passionate, Loyal
This entry was posted in C#, Software architecture. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s