我的问题来自这个问题:Is this possible with Unity (Instead of Castle Windsor)?
以下是答案中的课程:
protected override void Initialize()
{
var strategy = new AutoMockingBuilderStrategy(Container);
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
}
class AutoMockingBuilderStrategy : BuilderStrategy
{
private readonly IUnityContainer container;
private readonly Dictionary<Type, object> substitutes
= new Dictionary<Type, object>();
public AutoMockingBuilderStrategy(IUnityContainer container)
{
this.container = container;
}
public override void PreBuildUp(IBuilderContext context)
{
var key = context.OriginalBuildKey;
if (key.Type.IsInterface && !container.IsRegistered(key.Type))
{
context.Existing = GetOrCreateSubstitute(key.Type);
context.BuildComplete = true;
}
}
private object GetOrCreateSubstitute(Type type)
{
if (substitutes.ContainsKey(type))
return substitutes[type];
var substitute = Substitute.For(new[] {type}, null);
substitutes.Add(type, substitute);
return substitute;
}
}
发布的解决方案适用于SINGLE对象。如果您看到发布的解决方案,则每次调用Resolve时都会返回相同的对象
在以下测试用例中这很好:
var myObjectWithInnerMockedObjects = UnityContainer.Resolve<ISomeInterface>();
var internalAutoMockedObject = UnityContainer.Resolve<IInnerInterface>();
上述问题中公布的解决方案适用于上述情况。
上面的代码通过Unity创建一个对象并尝试解析构造函数参数,如果类型未在unity config中映射,则通过NSubstitute返回一个模拟。
如此有效的链条可能是:
- ActualObject
- InnerActualObjectDependency
- MockedDependency (since this was not mapped in Unity, a mock was created)
问题是如果我创建了2个这样的对象,则模拟指向相同的对象。
如果我删除CONTAINS检查,在方法GetOrCreateSubstitute()中,那么每次我都得到一个新的模拟...但是,如何访问特定对象的模拟以设置它的期望? : - (
我希望我对这个问题很清楚!!
答案 0 :(得分:1)
我们进行了内部团队讨论,并且我更好地理解,模拟意味着是单身人士。 按设计我们不希望为每个创建的对象使用不同的模拟对象。
模拟是针对类而不是方法。因此,以下伪代码将是实现我正在做的事情的完美方式。
var obj1 = Resolve<IMyInterface>();
var obj2 = Resolve<IMyInterface>();
var innerDependency = Resolve<IInnerType>(); // Returns the same object that is shared by above 2 objs
innerDependency.SetExpection(Some expectation);
obj1.PerformAction();
innerDependency.Assert();
innerDependency.SetExpection(Some *different* expectation);
obj2.PerformAction();
innerDependency.Assert();
所以这个问题的借口是错误的。我们没有这样的灵活性,因为我们不想!