在使用 Autofac 作为 IoC 容器,因为 Autofac 默认的创建时机是在主机运行时。而在此 Module 被 Load 时注入的对象的注入的时机,将会在单元测试 Fake 注入之后,这就意味着 Load 时注入的对象将会覆盖 Fake 的对象。可以通过调用 Autofac 的 PreserveExistingDefaults 方法解决覆盖的问题

在进行集成测试,需要注入一些 Fake 的或者 Mock 的等用来测试的对象,这些对象期望替换掉原有的业务逻辑的对象。而在使用 Autofac 框架,将因为对象创建时机的问题,而让单元测试不好玩

单元测试注入的顺序,是在业务对象注入之前,因此业务对象将会替换掉单元测试注入的对象

通过 PreserveExistingDefaults 方法,可以在框架判断,如果在此之前已有注册,那么将不再进行注册,代码如下

            builder.RegisterType<Foo>().As<IFoo>()
                // 通过 PreserveExistingDefaults 可以在已经注册过了的应用,不会被覆盖为 Foo 类型
                // 在单元测试使用,单元测试注入了测试用的消费者,可以不被覆盖
                .PreserveExistingDefaults();

此时就可以在单元测试中,通过如下代码注入 FakeFoo 对象

            Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                    webBuilder.UseTestServer(); //关键是多了这一行建立TestServer
                })
                // 使用 auto fac 代替默认的 IOC 容器 
                .UseServiceProviderFactory(new AutofacServiceProviderFactory(builder =>
                {
                    builder.RegisterModule(new FakeFooModule());
                }))

    class FakeFooModule : Autofac.Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType<FakeFoo>().As<FakeFoo>().As<IFoo>().SingleInstance();
        }
    }

上面代码就是尝试注入 FakeFoo 作为 IFoo 服务,在业务逻辑里面,将判断 IFoo 服务是否已注册,如果没有被注册,才注册为 Foo 对象

更多集成测试请看 asp dotnet core 基于 TestServer 做集成测试


本文会经常更新,请阅读原文: https://blog.lindexi.com/post/Autofac-%E9%80%9A%E8%BF%87-PreserveExistingDefaults-%E8%A7%A3%E5%86%B3%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95-Fake-%E5%AF%B9%E8%B1%A1%E8%A2%AB%E8%A6%86%E7%9B%96.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

如果你想持续阅读我的最新博客,请点击 RSS 订阅,推荐使用RSS Stalker订阅博客,或者前往 CSDN 关注我的主页

知识共享许可协议 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接: https://blog.lindexi.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系

无盈利,不卖课,做纯粹的技术博客

以下是广告时间

推荐关注 Edi.Wang 的公众号

欢迎进入 Eleven 老师组建的 .NET 社区

以上广告全是友情推广,无盈利