我的Web应用程序依赖于某个值的web.config条目(如FEATURE_ACTIVATED = true),那么如何测试读取此web.config条目的函数?
我想避免将web.config条目复制到单元测试项目中的app.config,因为需要额外的工作来同步文件。
答案 0 :(得分:4)
拉出读取配置数据的代码,然后在测试中使用依赖注入与模拟对象或模拟框架配对。
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();
}
答案 1 :(得分:1)
我也想尽可能避免这些,但有时候没有其他选择(特别是在使用遗留代码时)。
尽可能创建用于访问配置选项的界面 - 将其注入您正在访问配置的任何位置。
然后实现一个具体的类,将其委托给内置的配置类,这是要使用的默认实现。
为测试创建接口的模拟实现,并在测试时注入。
答案 2 :(得分:1)
我总是包装配置逻辑,以便在系统测试时替换(模拟)配置。
换句话说,我像这样包装我的配置:
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; }
}
}
然后,当系统正在测试时,我可以像这样模拟我的配置:
var settings = new Mock<IConfigurationSettings>();
settings.SetupGet(s => s.SmtpHost).Returns("127.0.0.1");
Resolver.Setup(r => r.Resolve<IConfigurationSettings>()).Returns(settings.Object);