zoukankan      html  css  js  c++  java
  • ASP.NET 系列:单元测试之ConfigurationManager

    通过ConfigurationManager使用.NET配置文件时,可以通过添加配置文件进行单元测试,虽然可以通过测试但达不到解耦的目的。使用IConfigurationManager和ConfigurationManagerWrapper对ConfigurationManager进行适配是更好的方式,ConfigurationManagerWrapper提供.NET配置文件方式的实现,如果需要支持其他配置,创建IConfigurationManager接口的不同的实现类即可。

    1.定义IConfigurationManager接口

    原本依赖ConfigurationManager的代码现在依赖IConfigurationManager。可以在单元测试时方便的Mock。

    public interface IConfigurationManager
    {
        NameValueCollection AppSettings { get; }
        ConnectionStringSettingsCollection ConnectionStrings { get; }
        object GetSection(string sectionName);
    }

    2.创建适配类ConfigurationManagerWrapper

    非单元测试环境使用ConfigurationManagerWrapper作为IConfigurationManager的默认实现。

    public class ConfigurationManagerWrapper : IConfigurationManager
    {
        public NameValueCollection AppSettings
        {
            get
            {
                return ConfigurationManager.AppSettings;
            }
        }
    
        public ConnectionStringSettingsCollection ConnectionStrings
        {
            get
            {
                return ConfigurationManager.ConnectionStrings;
            }
        }
    
        public object GetSection(string sectionName)
        {
            return ConfigurationManager.GetSection(sectionName);
        }
    }

    3.自定义泛型配置接口

    在我们的代码需要使用配置时,可以考虑创建通用的泛型接口也可以使用专用的强类型的接口。这里演示使用通用的接口。

    public interface IConfiguration
    {
        T Get<T>(string key, T @default);
    }

    4.实现泛型接口配置接口的.NET配置文件版本

    AppConfigAdapter直接不使用ConfigurationManager而是依赖IConfigurationManager接口。

    public class AppConfigAdapter : IConfiguration
    {
        private IConfigurationManager _configurationManager;
    
        public AppConfigAdapter(IConfigurationManager configurationManager)
        {
            this._configurationManager = configurationManager;
        }
    
        public T Get<T>(string nodeName, T @default)
        {
            var value = this._configurationManager.AppSettings[nodeName];
            return value == null ? @default : (T)Convert.ChangeType(value, typeof(T));
        }
    }

    5.对泛型配置接口的实现进行单元测试

    使用最流行的单元测试框架和Mock类库:xUnit+Moq进行单元测试。

    public class AppConfigAdapterTest
    {
        [Fact]
        public void GetStringTest()
        {
            var key = "key";
            var value = "value";
            var configuration = new AppConfigAdapter(this.GetConfigurationManager(o => o.Add(key, value.ToString())));
            Assert.Equal(configuration.Get(key, string.Empty), value);
        }
    
        [Fact]
        public void GetIntTest()
        {
            var key = "key";
            var value = 1;
            var configuration = new AppConfigAdapter(this.GetConfigurationManager(o => o.Add(key, value.ToString())));
            Assert.Equal(configuration.Get(key, int.MinValue), value);
        }
    
        [Fact]
        public void GetBoolTest()
        {
            var key = "key";
            var value = true;
            var configuration = new AppConfigAdapter(this.GetConfigurationManager(o => o.Add(key, value.ToString())));
            Assert.Equal(configuration.Get(key, false), value);
        }
    
        [Fact]
        public void GetDateTimeTest()
        {
            var key = "key";
            var value = DateTime.Parse(DateTime.Now.ToString());
            var configuration = new AppConfigAdapter(this.GetConfigurationManager(o => o.Add(key, value.ToString())));
            Assert.Equal(configuration.Get(key, DateTime.MinValue), value);
        }
    
        [Fact]
        public void GetDecimalTest()
        {
            var key = "key";
            var value = 1.1m;
            var configuration = new AppConfigAdapter(this.GetConfigurationManager(o => o.Add(key, value.ToString())));
            Assert.Equal(configuration.Get(key, decimal.MinValue), value);
        }
    
        private IConfigurationManager GetConfigurationManager(Action<NameValueCollection> set)
        {
            var appSettings = new NameValueCollection();
            set(appSettings);
            var configurationManager = new Mock<IConfigurationManager>();
            configurationManager.Setup(o => o.AppSettings).Returns(appSettings);
            return configurationManager.Object;
        }
    }

    运行结果:

    6.总结

    使依赖ConfigurationManager静态类的代码转换为依赖IConfigurationManager接口,运行时注入ConfigurationManagerWrapper实现类。单元测试时使用Mock模拟IConfigurationManager对象。

  • 相关阅读:
    Recommended Books for Algo Trading in 2020
    Market Making is simpler than you think!
    Top Crypto Market Makers of 2020
    Top Crypto Market Makers, Rated and Reviewed
    爬取伯乐在线文章(五)itemloader
    爬取伯乐在线文章(四)将爬取结果保存到MySQL
    爬取伯乐在线文章(三)爬取所有页面的文章
    爬取伯乐在线文章(二)通过xpath提取源文件中需要的内容
    爬取伯乐在线文章(一)
    爬虫去重策略
  • 原文地址:https://www.cnblogs.com/easygame/p/5176711.html
Copyright © 2011-2022 走看看