我正在为一项服务进行一些测试自动化,并想出了一个简洁的方法来汇总一些常见的设置和放大器。验证到'会话'课程。
从概念上讲,测试用例可能如下所示:
using (var managerSession = new Session(managerRole))
{
// A manager puts some items in warehouse
}
using (var employeeSession = new Session(employeeRole))
{
// An employee moves items from warehouse to store
}
using (var customerSession = new Session(customerRole))
{
// A customer can buy items from the store
}
在Session对象构造函数中,我建立了与我正在测试的服务的连接,每个角色等都有适当的身份验证,并且在会话Dispose()方法中,我有一个通用的验证块,例如,检查没有服务器在会话期间提出了一些错误或警告。
现在,当然,这有点滥用IDispose模式,如果使用块中的测试代码抛出异常并且验证块也抛出异常,则第二个异常将掩盖第一个异常。
从概念上讲,如果我们有这种情况:
using (var managerSession = new Session(managerRole))
{
Assert.IsTrue(managerSession.DoJob(), "Manager did not do his job");
}
...并且断言失败或对managerSession.DoJob()的调用抛出异常,然后我希望Session Dispose()方法跳过验证块,即
public void Dispose()
{
if (NoExceptionThrown())
{
Assert.IsFalse(this.serviceConnection.HasErrors(), "Service connection has errors");
}
this.serviceConnection.Dispose();
}
...如果“服务连接有错误”测试方法永远不会失败,如果它实际上失败并且'经理没有做他的工作'
我的问题是:这里是否可以实现'NoExceptionThrown()'方法?是否有一些可以检查的全局属性,或者可以使用Thread.CurrentThread中隐藏的东西?
更新
我的问题是不如何重构: - )
我当然可以使用这种模式:
Session.ForRole(managerRole, (session) => { /* Test code here */ });
使用静态方法ForRole()定义为
public static void ForRole(Role r, Action<Session> code)
{
var session = new Session(r);
try
{
code(session);
Assert.IsFalse(session.serviceConnection.HasErrors());
}
finally
{
session.Dispose();
}
}
但我很好奇是否存在某种抓住异常状态的方法,如上所述。
答案 0 :(得分:1)
如果IDisposable.Dispose
的重载带有类型Exception
的参数,以指示与finally
相关联的Dispose
上下文中有待处理的异常(如果有),那将会很有帮助它的清理。虽然Dispose
方法通常不应关心异常的细节,但在Dispose
方法期间可能会出现应向呼叫者报告的情况。从finally
抛出的任何异常都将替换调用者的Dispose
上下文中已挂起的任何异常,因此如果Dispose
方法可以在替换之前封装挂起的异常,将会很有帮助。不幸的是,没有这样的功能存在,我不希望有任何添加。
虽然有一些hacks可用于实现类似于所需效果的东西,但唯一的语义正确方法是将异常作为Dispose
方法的参数。任何其他方法的问题是可以从多个嵌套的finally
块中运行finally
,其中一些块具有挂起的异常,而其中一些则没有;检查执行上下文以确定嵌套最深{{1}}块的状态的代码可能会失败,如果该块不是保护被处理对象生命周期的块。
答案 1 :(得分:0)
嗯,一个肯定但又丑陋的方法是在你的班级上设一个bool(默认为false)。
using (var managerSession = new Session(managerRole))
{
Assert.IsTrue(managerSession.DoJob(), "Manager did not do his job");
managerSession.NoExceptionThrown = true;
}
我不认为你会比使用IDisposable模式更清洁。
在这个例子中,try ... catch ...最终可能会更好,因为你可以直接访问异常对象,你可以测试null-ness(是一个单词?)甚至可能存放以备后用。你不应该失去任何东西,因为using
最终只是尝试捕获的糖。