2010-06-30 60 views
2

我想设置对Moq中模拟对象的方法的期望。与此同时,使用Ninject时,只要调用者需要相应的接口,我就试着让内核返回我的设置模拟。为了更清楚起见,这里有一些伪代码.net的依赖注入和模拟框架

Class Car { 

    Void buildChassis() { 
     Engine = ObjectBuilder.get<Iengine>() 
     Engine.performCheckup() 
    } 
} 

当测试buildChassis时,我想插入一个模拟引擎。

Mock<Iengine>().setup().etc.etc.etc 

但是,Moq对Ninject不太好:我无法做到这一点。我想知道是否有任何强大的软件包可以集成DI和嘲讽。我无法使ninject.moq包工作,也没有成熟。

回答

3

我使用和Moq一样,但使用与Ninject不同的IoC容器。我从来没有觉得需要整合模拟/隔离和IoC容器框架。我使用构造函数注入,然后在单元测试中将模拟对象传递给我的类。只有生产代码使用容器。

恕我直言,这里真正的问题是汽车知道ObjectBuilder。而不是使用容器作为服务定位器,为什么不做构造函数注入?这样,只有一个顶级类需要了解有关IoC容器的任何信息。

class Car 
{ 
    public Car(IEngine engine) 
    { 
     // May want a null check here 
     Engine = engine; 
    } 

    public IEngine Engine { get; private set; } 
} 

测试汽车隔离很容易;创建一个模拟IEngine并将其传递给构造函数。

如果您需要稍后创建引擎,则可以传入工厂界面。

如果您决定更改为其他IoC框架,则只需更改一个或两个顶级类。

+0

那么,在某些情况下,你真的需要创建一个类的新实例,只是将它添加到列表,例如等效。你会如何测试这些情况? (我有这个需要......) – 2010-06-30 17:50:49

+0

@Andrei:用创建IEngine实例的方法注入一个IEngineFactory(单向;也可以注入一个委托)。 Moq可以模拟工厂,然后设置create方法的返回值以返回另一个模拟。 – TrueWill 2010-06-30 18:02:39

+0

另请参阅http://www.tavaresstudios.com/Blog/post/Unity-20-Automatic-Factories.aspx - 不确定Ninject是否具有此功能。 – TrueWill 2010-06-30 18:04:27

0

+ 1'd其他答案 - 一个让所有东西都能正常工作的巨大魔法工具很少是正确的答案。考虑一下你是否需要在测试中进行大量设置,试图告诉你关于代码结构的一些信息,这一点很重要。此外,您不希望将测试绑定到太多垃圾 - 理想情况下,一次只能处理一个单元,并仔细考虑所添加的任何依赖关系。如果您的测试环境设置(排列)结束并且执行了大量不属于您的测试的通用内容,这将成为相互依存关系和巧合之间的一个磁场,这些相互依存关系和巧合将雪球变成泥球。最终导致您无论何时想要调整生产代码的某个方面,都必须重新安排测试代码。

但有http://github.com/ninject/ninject.moq