Tom*_*her 5 c# unity-container
我现在的场景是我正在编写一些代码的单元测试,该代码使用另一个使用依赖注入的代码库,并提供一个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;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,IFooBar类型解析为具体的FooBar类而不是Mocked版本.
我怀疑在重新注册时调用RegesterType <T>而不是RegisterType <TFrom,TTo>可能是个问题.
以下是第二次调用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";
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
给出相同的结果 - 这是第一次注册用于任何后续注册:

我会说这算作Unity中的一个错误,但是如果你已经将接口注册到具体类型,那么即使使用了工厂方法,覆盖注册也必须包含一个具体的类型.
在你的例子中:
container.RegisterType<IFooBar, FooBar>();
//Re-registering
container.RegisterType<IFooBar, FooBar>(new InjectionFactory(uc => MockFooBar));
Run Code Online (Sandbox Code Playgroud)
我验证了覆盖注册中的类型可以是实现接口的任何具体类型.