我的代码使用的是一个第三方库,该库内部采用了单例模式。在第一次访问时,该库使用windows环境变量来识别加载它的配置文件夹。
但是,我希望在不同的单元测试集中针对不同的文件夹运行。理想情况下,我会为每个单元测试类或诸如此类的类指定配置文件夹。
第三方库是一个巨大的对象模型,我的代码只是它们之上的一组扩展方法。我看不出有什么简单的方法可以嘲弄整个图书馆。
有什么方法可以为每个测试类创建一个新的appdomain吗?我知道负载测试有一个在运行测试程序集之间创建域的设置。在我的情况下,这将是很多程序集,我不太确定是否/如何在单元测试运行程序上设置此设置。
或者,我正在考虑购买Typemock Isolator或JustLock,这样我就可以让singleton返回一个"null",从而导致第三方库加载一个新的。我看过反编译的代码,它似乎可以达到预期的结果。当然,那里可能隐藏着更多的"好东西"。
这些都是人为的做法。我真正想要的是在测试、测试类或测试程序集之间"刷新"整个appdomain。
当自动化测试需要切换配置文件夹时,我愿意牺牲速度。红绿重构周期可能不会包括多个配置文件夹。
关于如何实现这一目标,有什么建议吗?
编辑我刚刚发现,不同的测试程序集会导致singleton被擦除。因此,可以根据测试程序集运行的配置来组织测试程序集,而不是根据测试所针对的依赖项或问题域。
如果您要进行真正的单元测试(而不是集成测试等),我建议包装外部依赖项。
我看不出有什么简单的方法可以嘲弄整个图书馆。
看看立面图案。你提到它有一个巨大的对象模型;很可能您的代码正在与其中的一小部分进行交互。考虑让facade具有声明性,因为它的方法描述了你试图实现的目标,而不是如何实现。facade不一定是通用的,它只需要为您的应用程序工作即可。
确保facade实现了一个或多个接口。通常,您会希望一个或多个工厂返回具体实现的实例。
代码的其余部分都只使用facade。工厂只能在一个地方调用(或者可以添加工厂接口);其他一切都是通过依赖注入完成的。
要对其余类(除了facade之外的所有类)进行单元测试,可以注入mock对象。
您的包装器代码应该是非常薄的一层。您仍然需要针对实际库进行集成测试。
分散在不同的测试组件中
将单元测试类扩展到不同的测试程序集将导致testrunner创建新的appdomain,因此singleton将被擦除。因此,可以根据测试程序集运行的配置来组织测试程序集,而不是根据测试所针对的依赖项或问题域。
但由于以下原因,此解决方案可能不适用于所有人:
这有可能创建一个包含大量测试项目(针对各种测试数据)的混乱解决方案。由此产生的结构与按组件和问题域组织单元测试的标准做法相反。
我没有触及单身人士的数据。它只是一个后备数据参考库。单元测试的主要指示是它们不应相互影响或要求特定的顺序。
单元测试的另一个主要指示是它们应该快速运行。幸运的是,在正常的红->绿->重构周期中,我不必针对多个测试配置运行。更大的测试组件套件将是回归测试。