我目前的情况是,我正在为一些代码编写单元测试,这些代码使用另一个代码库,该代码库使用依赖注入(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 后容器在运行时的截图:
使用另一个“非模拟”类似乎也会发生同样的情况,这并不奇怪,因为希望 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";
}
}
}
}
给出相同的结果 - 即第一个注册用于任何后续注册:
最佳答案
我会说这算作 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/