Ste*_*ers 2 c# enterprise-library exception-handling
我有一个方法可以做一些IO,通常看起来像这样:
public bool Foo()
{
try
{
// bar
return true;
}
catch (FileNotFoundException)
{
// recover and complete
}
catch (OtherRecoverableException)
{
// recover and complete
}
catch (NonRecoverableException ex)
{
ExceptionPolicy.HandleException(ex, "LogException");
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
该方法不是完成任务的关键,有外部恢复步骤 - 并且抛出NonRecoverableException是相对常见的 - 它在规范中返回false,报告'此时无法完成'并且处理移动.NonRecoverableException不会将程序置于无效状态.
当我进行单元测试时,抛出其中一个异常,我得到了错误
Activation error occured while trying to get instance of type ExceptionPolicyImpl
Run Code Online (Sandbox Code Playgroud)
而且我想压制它,而不是获取实际/原始异常信息,而不是EntLib无法记录(并且,实际上强制NonRecoverableException并且具有[ExpectedException(typeof(NonRecoverableException))]单元测试以确保这种方法符合规范.
我怎么能这样做?
编辑 使用预处理程序指令并不理想,因为我讨厌在代码库中看到特定于测试的代码.
Chr*_*res 10
使用Entlib静态外观的代码的可测试性很难.在不改变代码的情况下,您唯一的答案是将app.config文件添加到测试程序集中,并使用无效的无害策略设置Entlib异常块.
然而,在Entlib 4(和我看到你正在使用的5)中,还有另一种方式.我们为所有块添加了一个实例入口点,专门用于改进可测试性故事.对于异常块,该实例是ExceptionManager.使用它非常简单.获取一个异常管理器实例到您的类型,然后调用它而不是ExceptionPolicy.像这样的东西:
public class Whatever {
private ExceptionManager exm;
public Whatever(ExceptionManager exm) { this.exm = exm; }
public bool Foo() {
try {
... do whatever ...
}
catch(NonRecoverableException ex) {
exm.HandleException(ex, "LogException");
return false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在你已经有了它,你可以模拟出ExceptionManager(它是一个抽象的基类),在测试过程中基本上没有操作它,无论是手动还是使用模拟对象框架.
如果您不想强制用户使用DI容器,可以添加一个获取当前异常管理器的默认构造函数:
public class Whatever {
private ExceptionManager exm;
public Whatever() : this(EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>()) { }
public Whatever(ExceptionManager exm) { this.exm = exm; }
}
Run Code Online (Sandbox Code Playgroud)
最终用户使用默认构造函数,您的测试使用接受显式ExceptionManager的测试,并且您可以使用钩子来模拟Entlib使用的任何内容.
现在所有的块都有这些"管理器"类(无论如何它们都有意义).