Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 如何在集成测试中模拟装饰类_.net_Integration Testing_Inversion Of Control_Decorator_Castle Windsor - Fatal编程技术网

.net 如何在集成测试中模拟装饰类

.net 如何在集成测试中模拟装饰类,.net,integration-testing,inversion-of-control,decorator,castle-windsor,.net,Integration Testing,Inversion Of Control,Decorator,Castle Windsor,我们在项目中使用了温莎城堡。我们有Installer:IWindsorInstaller类,它包含Install方法以及特定项目的所有注册 现在我想写一个集成测试,它将测试所有类上的一些“快乐场景”,只使用模拟的数据源。这意味着我想使用模拟数据源,而不是生产代码中使用的普通SQL数据源 问题是由于数据源是使用Castle Windsor的decorator支持进行修饰的。这意味着我首先注册装饰器链(按照想要的顺序),然后注册真实的数据源。集成测试想要调用生产代码的Install方法,但是需要在那

我们在项目中使用了温莎城堡。我们有
Installer:IWindsorInstaller
类,它包含
Install
方法以及特定项目的所有注册

现在我想写一个集成测试,它将测试所有类上的一些“快乐场景”,只使用模拟的数据源。这意味着我想使用模拟数据源,而不是生产代码中使用的普通SQL数据源

问题是由于数据源是使用Castle Windsor的decorator支持进行修饰的。这意味着我首先注册装饰器链(按照想要的顺序),然后注册真实的数据源。集成测试想要调用生产代码的
Install
方法,但是需要在那里放置一个模拟的数据源,而不是真实的数据源。如果没有decorator,我们可以简单地使用
IsDefault
强制容器使用mock而不是最初注册的生产类。但这在decorators中是不可能的,因为它覆盖了整个decorator链

在生产代码中,链类似于:客户机->缓存->计算->数据源

在集成测试中,我想要像这样的链:客户端->缓存->计算->模拟数据

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>());
container.Register(Component.For().ImplementedBy());
container.Register(Component.For().ImplementedBy());
container.Register(Component.For().ImplementedBy());
我现在需要的是跳过最后一个注册。但是如果我在集成测试中编写一个单独的注册代码,它将不会测试安装方法是否正确编写。我试图找到一个解决方案,它将与生产代码中的安装方法一起工作

到目前为止我所尝试的:由于Castle Windsor没有找到任何真正的解决方案,我将
Install
方法拆分为两个方法,生产代码调用这两个方法来注册所有内容,但集成测试不调用包含最后一次注册的方法。不幸的是,此解决方案要求生产代码按特定顺序调用这两个安装方法,否则它将无法工作。因此,我再次创建了一些危险的代码,这些代码在正常的NUnit测试中是不稳定的。(这是读到的,我错误地颠倒了这些注册的顺序,直到有人在生产代码中使用它,它才可见…)

在生产代码中,该链类似于:客户机->缓存->计算 ->数据源

在集成测试中,我想要像这样的链:客户端->缓存->计算->模拟数据

从任务的这种表述中,我非常清楚,
Installer
应该使用数据源的类型(
DataSource
MockedData
)进行参数化

由于
Installer
实现Castle
IWindsorInstaller
接口,并且您不能更改方法
Install
,因此您可以使用数据源类型将
Installer
设置为a类通用:

public class Installer<TDataRepository> : IWindsorInstaller where TDataRepository : IRepository
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Component.For<IRepository, ICacheService<int, List<MyData>>>().ImplementedBy<MyDataCache>());
        container.Register(Component.For<IRepository>().ImplementedBy<ComputedColumns>());
        container.Register(Component.For<IRepository>().ImplementedBy<TDataRepository>());
    }
}
公共类安装程序:IWindsorInstaller其中TDataRepository:IRepository
{
public void安装(IWindsorContainer、IConfigurationStore)
{
container.Register(Component.For().ImplementedBy());
container.Register(Component.For().ImplementedBy());
container.Register(Component.For().ImplementedBy());
}
}
现在,您可以为生产代码和集成测试设置所需的不同实现:

//  In production code
container.Install(new Installer<DataRepository>());

//  In integration test
container.Install(new Installer<MockedRepository>());
//在生产代码中
container.Install(新安装程序());
//在集成测试中
container.Install(新安装程序());

这种解决方案没有您所描述的“两种方法”方法的任何缺点。

我们不能完全做到这一点,因为我们的安装程序是按照约定自动调用的。我的意思是我的代码在插件中,我没有访问容器的权限。系统只是扫描程序集中的所有IWindsorInstaller实现并调用它们。我认为这个答案更像是一个解决方案,而不是我问题的真正解决方案。当然,我可以自己注册。我想要实现的是能够在集成测试中使用真正的生产代码安装程序,并通过在我调用真正的生产代码安装程序之前或之后执行一些操作来调整某些特定的注册。至于按约定注册,您可以使该通用安装程序成为一个抽象类(例如,
InstallerT
),然后有一个具体的实现,它只是继承自
InstallerT
。温莎将正确地调用它。关于你的第二条评论-我看不到其他修改
Install()中设置的装饰器链的可能性
method。您可以在之前或之后添加更多的装饰器,但这不会帮助您避免调用
DataSource
实现。