开发者

Visual Studio 2008 - Unit testing with web config settings

My web application depends on a web.config entry being a certain value (like FEATURE_ACTIVATED=true) so how do I test the function that reads this web.config entry?

I'd like to avoid copying the web.config entries to开发者_Python百科 an app.config in the unit testing project, as it takes extra effort to synchronize the files.


Pull out the code that reads configuration data, then use dependency injection paired with a mock object, or a mocking framework in your tests.

public interface IConfiguration
{
  bool IsAwesomeFeatureActivated { get; }
}

public class Configuration: IConfiguration
{
  public bool IsAwesomeFeatureActivated
  { 
    get { /* get config value */ }
  }
}

public class AwesomeFeature
{
  private IConfiguration _configuration;

  public AwesomeFeature(IConfiguration configuration)
  {
    _configuration = configuration;
  }

  public void ExecuteFeature()
  {
    if(! _configuration.IsAwesomeFeatureActivated) return;
    // do awesome feature functionality
  }
}

public class MockConfiguration: IConfiguration
{
  private bool _isAwesomeFeatureActivated;
  public void SetIsAwesomeFeatureEnabled(bool value)
  {
    _isAwesomeFeatureActivated = value;
  }

  public bool IsAwesomeFeatureActivated
  {
    get { return _isAwesomeFeatureActivated; }
  }
}

// with mock object
[Test]
public void ExecuteFeature_WhenNotActivated_DoNothing()
{
  var mockConfig = new MockConfiguration();
  mockConfig.SetIsAwesomeFeatureActivated(false);
  var feature = new AwesomeFeature(mockConfig);
  feature.ExecuteFeature();
  Assert.SomethingHere();
}

// or with Moq framework
[Test]
public void ExecuteFeature_WithActivated_DoSomething()
{
  var mock = new Mock<IConfiguration>();
  mock.Setup(c => c.IsAwesomeFeatureActivated).Returns(true);

  var feature = new AwesomeFeature(mock.Object);
  feature.ExecuteFeature();

  Assert.SomethingHere();
}


I also like avoiding these where possible, but sometimes there are not other options (particularly when working with legacy code).

Where you can, create an interface for accessing configuration options - inject it into any place you are accessing configuration.

Then implement a concrete class that delegates that to the built in configuration classes, that's the default implementation to use.

Create a mock implementation of the interface for your testing and inject that when testing.


I always wrap the configuration logic so that I can replace (mock) the configuration while the system is under test.

In other words, I wrap my configuration like so:

    public interface IConfigurationSettings
    {
        string SmtpHost { get; }
    }

    public class ConfigurationSettings : IConfigurationSettings
    {
        public string SmtpHost
        {
            get { return ConfigurationManager.AppSettings["SmtpHost"]; }
        }
    }

    public static class Settings
    {
        private static readonly IConfigurationSettings _configurationSettings;

        static Settings()
        {
            _configurationSettings = IoCHelper.Resolve<IConfigurationSettings>();
        }

        public static string SmtpHost
        {
            get { return _configurationSettings.SmtpHost; }
        }
}

Then, when the system is under test, I can just mock out my configuration like so:

var settings = new Mock<IConfigurationSettings>();
settings.SetupGet(s => s.SmtpHost).Returns("127.0.0.1");
Resolver.Setup(r => r.Resolve<IConfigurationSettings>()).Returns(settings.Object);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜