• IOC容器Autofac的另类使用


    最近在公司项目中使用了Autofac,本人需要解决的问题比较特别,就是需要在单元测试时候替换实际处理的类,通过模拟数据库操作完成单元测试。

    本人是个懒惰的程序员,因为不想修改autofac的配置文件,又要结合fakes进行模拟,在网上又未发现类似处理方法,所以特把自己的做法共享出来,供大家参考和改进。

    因为实际代码为公司项目,未能尽列代码请见谅,同时认为应该还有更好的改进方案,请有更好想法的朋友分享。

    部分参考代码
    ------------------------------------------------

     DAO管理器:

     /// <summary>
        /// Dao 管理器
        /// </summary>
        public class DaoBag
        {
            #region 防实例静态化
    		/// <summary>
    		/// 获取实例
    		/// </summary>
    		public static DaoBag Instance
    		{
    			get
    			{
    				return Nested.instance;
    			}
    		}
    		/// <summary>
    		/// 密封的内部嵌套辅助类,辅助创建单例对象
    		/// </summary>
    		sealed class Nested
    		{
    			// 静态钩子
    			static Nested()
    			{
    			}
    			/// <summary>
    			/// 只读类型
    			/// </summary>
                internal static readonly DaoBag instance = new DaoBag();
    		}
    		// 防止直接实例化
            private DaoBag() {
                builder.RegisterModule(new ConfigurationSettingsReader("autofac"));
            }
    		#endregion
    
            ContainerBuilder builder = new ContainerBuilder();
            IContainer container;
    
            public T GetDao<T>()
            {
                // 延迟加载,第一次使用时候被调用
                if (container == null) container = builder.Build();
    
                return container.Resolve<T>();
            }
    
            public void SetDao<T,I>(T t) where T : class
            {
                builder.RegisterInstance<T>(t).As<I>();            
            }
        }
    

     Config配置(无论单元测试还是实际项目中,配置文件不变,这也是我非常需要偷懒的地方)

    <configuration>
        <configSections>
            <section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration"/>
        </configSections>
    <autofac defaultAssembly="Model">
        <components>
            <component type="Model.Help.HelpNewsRepository, Model" service="Model.Help.IHelpNewsRepository" />
            <component type="Model.Pri.PriUserRepository, Model" service="Model.Pri.IPriUserRepository" />
        </components>
    </autofac>
    </configuration>
    View Code

    最终完成后实现的效果如下
    ------------------------------------------------------

    业务类中使用方法:
    private IHelpNewsRepository hnr = DaoBag.Instance.GetDao<IHelpNewsRepository>();

    单元测试中替换方法(注意使用了Fakes,单元测试中的替换将使配置失效,其实不是单元测试和实际项目使用相同配置,应该说是单元测试不用配置):

    // 准备测试数据
                var news_id = 1;
                var news_viewNum = 2;
    
                // 准备伪造数据处理类
                StubIHelpNewsRepository stubhnr = new StubIHelpNewsRepository();
                StubIPriUserRepository stubpur = new StubIPriUserRepository();
    
                // 模拟底层数据处理方法
                stubhnr.GetEntityInt64 = (x) =>
                    {
                        return new HelpNews { Title = "新闻测试", Id = 1, ViewNum = 1 };
                    };
                
                stubpur.GetEntityInt64 = (x) =>
                    {
                        return new PriUser { Id = 1, Username = "admin" };
                    };
    
                // 为IOC容器设置新的Dao (注意:必须设置完所有相关Dao映射,才可以进行其他步骤)
                DaoBag.Instance.SetDao<StubIHelpNewsRepository, IHelpNewsRepository>(stubhnr);
                DaoBag.Instance.SetDao<StubIPriUserRepository, IPriUserRepository>(stubpur);
                
                //测试第一个业务类
                var newbus = NewsBus.Instance;            
                var result = newbus.GetNews(news_id).AppendData as HelpNews;
    
                Assert.AreEqual(news_id, result.Id);
                Assert.AreEqual("新闻测试", result.Title);
                Assert.AreEqual(news_viewNum, result.ViewNum);
    
                //测试第二个业务类
                var userbus = UserBus.Instance;
                var user = userbus.GetUser(1).AppendData as PriUser;
                Assert.AreEqual(user.Username, "admin");
    View Code
  • 相关阅读:
    很简单的企业管理器我写程序的方式,几个自定义控件。
    当OO遇到了持久化?!
    [自定义服务器控件] 第一步:文本框。
    [面向过程——老酒换新瓶] (一)开篇:是面向过程还是面向对象?
    个人理财小助手 —— 设计思路、功能说明
    《Head First 设计模式》 终于出中文版了。
    其实添加数据也可以这样简单——表单的第一步抽象(针对数据访问层)《怪怪设计论: 抽象无处不在 》有感
    基类、接口的应用——表单控件:一次添加、修改一条记录,一次修改多条记录。(上)
    其实添加数据也可以这样简单——表单的第三步抽象(针对UI及后置代码)
    转帖:客户端表单通用验证checkForm(oForm) js版
  • 原文地址:https://www.cnblogs.com/gamer/p/3134230.html
Copyright © 2020-2023  润新知