【发布时间】:2018-01-25 15:28:22
【问题描述】:
我们在项目中使用 Castle Windsor。我们有 Installer : IWindsorInstaller 类,其中包含 Install 方法以及特定项目的所有注册。
现在我想编写一个集成测试,它将在所有类上测试一些“快乐场景”,只使用模拟数据源。这意味着我想使用模拟数据源而不是生产代码中使用的普通 SQL 数据源。
问题是由使用 Castle Windsor 的装饰器支持来装饰数据源的事实引起的。这意味着我首先注册装饰器链(以某种想要的顺序),然后注册真正的数据源。集成测试想要调用生产代码的Install 方法,但需要放一个模拟数据源而不是真实数据源。如果没有装饰器,我们可以简单地使用IsDefault 来强制容器使用模拟而不是最初注册的生产类。但这对于装饰器是不可能的,因为它会覆盖整个装饰器链。
在生产代码中,链就像:客户端 -> 缓存 -> 计算 -> 数据源
在集成测试中,我想要这样的链:客户端 -> 缓存 -> 计算 -> MockedData
Install 中的代码如下:
container.Register(Component.For<IRepository, ICacheService<int, List<MyData>>>().ImplementedBy<MyDataCache>());
container.Register(Component.For<IRepository>().ImplementedBy<ComputedColumns>());
container.Register(Component.For<IRepository>().ImplementedBy<DataRepository>());
我现在需要的是跳过最后一个注册。但是如果我在集成测试中单独编写一个注册码,它不会测试Install方法是否正确编写。我正在尝试找到一个可以与生产代码中的安装方法一起使用的解决方案。
到目前为止我尝试了什么:由于我没有找到任何真正的温莎城堡解决方案,我将Install 方法拆分为两个方法,生产代码调用它们来注册所有内容,但集成测试没有调用包含最后一次注册的那个。不幸的是,此解决方案要求生产代码以特定顺序调用这两个 Install 方法,否则它不起作用。因此,我再次创建了一些危险的代码,这些代码无法通过正常的 NUnit 测试来测试。 (这是阅读,我错误地颠倒了这些注册的顺序,直到有人在生产代码中使用它才可见......)
【问题讨论】:
标签: .net integration-testing inversion-of-control decorator castle-windsor