c# - 替换 Unity RegisterType<From, To> 与 RegisterType<T> 中的注册类型

标签 c# unity-container

我目前的情况是,我正在为一些代码编写单元测试,这些代码使用另一个代码库,该代码库使用依赖注入(inject)并提供 UnitContainerExtension 来引导库所需的所有具体类。但是在我的单元测试中,我希望能够模拟一两个已注册的类型。现在理论上,根据我能看到的所有帖子,注册然后重新注册一个类型应该没有问题。后者的定义/映射取代了前者。

但是这在实践中似乎行不通。现在我可以从库扩展中复制类型注册列表,并省略/更改我需要模拟的那些。但是我认为这似乎不对,也许我遗漏了什么。

以下是代码示例(经过简化并内联了 UnitContainerExtension):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using Moq;

namespace UnityTest
{
    class Program
    {
        private static IFooBar _mockFooBar;

        public static IFooBar MockFooBar
        {
            get
            {   
                return _mockFooBar ?? (_mockFooBar = Mock.Of<IFooBar>(fb => fb.Test(It.IsAny<string>()) == "I am mockery of FooBar!"));
            }
        }

        static void Main(string[] args)
        {
            UnityContainer container = new UnityContainer();

            //Registration of concrete class done inside extension
            container.RegisterType<IFooBar, FooBar>();

            //Re-registering
            container.RegisterType<IFooBar>(new InjectionFactory(uc => MockFooBar));

            //This should resolve to the mocked foobar but doesn't
            Console.WriteLine(container.Resolve<IFooBar>().Test("I am the concrete FooBar!"));
            Console.ReadLine();
        }

        public interface IFooBar
        {
            string Test(string text);
        }

        public class FooBar : IFooBar
        {
            public string Test(string text)
            {
                // Some concrete code
                return text;
            }
        }
    }
}

但是 IFooBar 类型解析为具体的 FooBar 类而不是 Mocked 版本。

我怀疑在重新注册时调用 RegesterType 而不是 RegisterType 可能是问题所在。

下面是第二次调用 RegisterType 后容器在运行时的截图: enter image description here

使用另一个“非模拟”类似乎也会发生同样的情况,这并不奇怪,因为希望 Unity 不会查看映射到对象的类型。

使用以下修改后的示例源:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using Moq;

namespace UnityTest
{
    class Program
    {
        private static IFooBar _mockFooBar;

        public static IFooBar MockFooBar
        {
            get
            {   
                return _mockFooBar ?? (_mockFooBar = Mock.Of<IFooBar>(fb => fb.Test(It.IsAny<string>()) == "I am mockery of FooBar!"));
            }
        }

        static void Main(string[] args)
        {
            UnityContainer container = new UnityContainer();

            //Registration of concrete class done inside extension
            container.RegisterType<IFooBar, FooBar>();

            //Re-registering
            container.RegisterType<IFooBar>(new InjectionFactory(uc => MockFooBar));

            //Re-registering
            container.RegisterType<IFooBar>(new InjectionFactory(uc => new FooBar2()));

            //This should resolve to the mocked foobar but doesn't
            Console.WriteLine(container.Resolve<IFooBar>().Test("I am the original FooBar!"));
            Console.ReadLine();
        }

        public interface IFooBar
        {
            string Test(string text);
        }

        public class FooBar : IFooBar
        {
            public string Test(string text)
            {
                // Some concrete code
                return text;
            }
        }


        public class FooBar2 : IFooBar
        {
            public string Test(string text)
            {
                // Some concrete code
                return "FooBar 2.0";
            }
        }
    }
}

给出相同的结果 - 即第一个注册用于任何后续注册:

enter image description here

最佳答案

我会说这算作 Unity 中的一个错误,但如果您已经将接口(interface)注册到具体类型,则覆盖注册必须包含具体类型即使使用了工厂方法。

在你的例子中:

        container.RegisterType<IFooBar, FooBar>();

        //Re-registering
        container.RegisterType<IFooBar, FooBar>(new InjectionFactory(uc => MockFooBar));

我已验证您覆盖注册中的类型可以是实现该接口(interface)的任何具体类型。

关于c# - 替换 Unity RegisterType<From, To> 与 RegisterType<T> 中的注册类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22912379/

相关文章:

c# - 使用泛型清理代码

c# - 了解内存性能计数器

c# - Azure 辅助角色的多个实例有多少个队列?

c# - 你如何模拟 IUnityContainer?

c# - 在创建容器时将无参数构造函数设置为注入(inject)构造函数

c# - Unity 3 和错误 "The type name or alias "xxxxx“无法解析。请检查您的配置文件并验证此类型名称。”

c# - SQL Server 2008 中的事件机制

c# - AES 管理的加密值总是以 ==?

c# - 在 ASP.NET 中的 Server.Transfer 之后使用依赖注入(inject) BuildUp

c# - 使用统一容器 : "The underlying provider failed on Open" 具有连接字符串的 EF 多个构造函数