我目前的场景是我正在编写一些代码的单元测试,该代码使用另一个使用依赖注入的代码库,并提供一个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&lt; T&gt;而不是RegisterType&lt; TFrom,TTo&gt;重新注册可能是个问题。
以下是第二次调用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";
}
}
}
}
给出相同的结果 - 即第一次注册用于任何后续注册:
答案 0 :(得分:9)
我认为这算作Unity中的一个错误,但是如果您已经将接口注册到具体类型,则覆盖注册必须包含具体类型,即使使用了工厂方法。< / p>
在你的例子中:
container.RegisterType<IFooBar, FooBar>();
//Re-registering
container.RegisterType<IFooBar, FooBar>(new InjectionFactory(uc => MockFooBar));
我确认您的覆盖注册类型可能是实现该界面的任何具体类型。