[英]Ninject kernel binding overrides
我只是想知道在内核中重新绑定绑定的最佳做法是什么。
我有一个带有内核的类和一个带有默认生产绑定的私有类模块。
对于测试,我想覆盖这些绑定,以便我可以交换我的Test Doubles / Mocks对象。
不
MyClass.Kernel.Load(new InlineModule(m=> m.Bind<IDepend>().To<TestDoubleDepend>()))
覆盖IDepend的任何现有绑定?
我尝试尽可能少地在我的代码中直接使用DI内核,而不是依赖于构造函数注入(或选择情况下的Attribute
,例如Attribute
类)。 但是,我必须使用抽象层,以便我可以设置DI内核对象,使其在单元测试中可模拟。
例如:
public interface IDependencyResolver : IDisposable
{
T GetImplementationOf<T>();
}
public static class DependencyResolver
{
private static IDependencyResolver s_resolver;
public static T GetImplementationOf<T>()
{
return s_resolver.GetImplementationOf<T>();
}
public static void RegisterResolver( IDependencyResolver resolver )
{
s_resolver = resolver;
}
public static void DisposeResolver()
{
s_resolver.Dispose();
}
}
使用这样的模式,您可以通过使用模拟或伪实现调用RegisterResolver
来设置单元测试中的IDependencyResolver
,该实现返回您想要的任何对象,而无需连接完整模块。 如果您将来选择切换到另一个容器,它还具有从特定IoC容器中抽象代码的第二个好处。
当然,您还需要根据需要向IDependencyResolver
添加其他方法,我只是将这里的基础知识作为示例。 是的,这将要求您在Ninject内核周围编写一个超级简单的包装器,它也实现了IDependencyResolver
。
你想要这样做的原因是你的单元测试应该只测试一件事,并且通过使用你的实际IoC容器,你实际上比一个被测试的类更多地运动,这可能导致错误的负面因素,使你的测试脆弱和(更重要的是)随着时间推移开发人员对其准确性的信心。 这可能导致测试冷漠和放弃,因为测试失败但软件仍然可以正常工作(“不用担心,一个总是失败,这不是什么大不了的事”)。
我只是希望这样的事情有效
var kernel = new StandardKernel(new ProductionModule(config));
kernel.Rebind<ITimer>().To<TimerImpl>().InSingletonScope();
ProductionModule是我的生产绑定,我通过在特定测试用例中调用Rebind来覆盖。 我在重新绑定的几件物品上打电话重新绑定。
优点:如果有人向生产模块添加了新的绑定,我会继承它们,因此它不会以这种方式破坏,这可能很好。 这一切都适用于Java中的Guice ...希望它也可以在这里工作。
我倾向于做一个单独的测试项目完成它自己的绑定 - 我当然假设我们正在谈论某种单元测试。 测试项目使用自己的内核并将测试项目中的模块加载到该内核中。 项目中的测试在CI构建期间执行,并通过构建脚本执行完整构建,但测试从未部署到生产中。
我意识到你的项目/解决方案设置可能不允许这种组织,但从我看到的看起来似乎很典型。
Peter Mayer的方法对于单元测试很有用,但恕我直言,使用构造函数/属性注入手动注入Mock是不是更容易?
在我看来,对测试项目使用特定绑定对于其他类型的测试(集成,功能)更有用,但即使在这种情况下,您肯定需要根据测试更改绑定。
我的方法是某种kronhrbaugh和Hamish Smith的混合,创建了一个“依赖解析器”,你可以注册和注销要使用的模块。
我会向MyClass添加一个接受模块的构造函数。
这不会用于生产,但会用于测试。
在测试代码中,我将传递一个模块,该模块定义了所需的测试双精度数。
对于我正在进行的项目,我为每个环境(测试,开发,阶段,生产等)创建了单独的模块。 这些模块定义了绑定。
因为dev,stage和production都使用了许多相同的绑定,所以我创建了一个共同的模块。 然后每个人都添加环境特定的绑定。
我还有一个KernelFactory,当传递一个环境令牌时,它将使用适当的模块对一个IKernel进行假脱机。
这允许我切换我的环境令牌,这反过来会自动更改我的所有绑定。
但是如果这是用于单元测试的话,我同意上面的评论,即允许手动绑定的简单构造函数是一种方法,因为它使Ninject远离你的测试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.