繁体   English   中英

如何检查是否已抛出任何异常?

[英]How can I check if any exception has already been thrown?

我正在为一项服务进行一些测试自动化,并找到了一种巧妙的方法,将一些常见的设置和验证汇总到一个“会话”课程中。

从概念上讲,测试用例可能如下所示:

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();
    }
}

但我很好奇是否存在一些抓住异常状态的方法,如上所述。

如果有一个IDisposable.Dispose的重载,它会使用一个Exception类型的参数来指示在与其清理相关的finally上下文中有哪些异常(如果有的话)处于挂起状态。 虽然Dispose方法通常不应关心异常的细节,但Dispose方法中可能会出现应向调用者报告的情况。 Dispose抛出的任何异常都将替换调用者的finally上下文中已挂起的任何异常,因此如果Dispose方法可以在替换之前封装挂起的异常将会很有帮助。 不幸的是,没有这样的功能存在,我不希望任何添加。

虽然有一些hacks可用于实现类似于所需效果的东西,但唯一的语义正确方法是将异常作为Dispose方法的参数。 任何其他方法的问题是Dispose可以从多个嵌套的finally块中运行,其中一些具有挂起的异常,而其中一些则没有; 如果该块不是保护被处置对象的生命周期的块,则检查执行上下文以确定最深嵌套的finally块的状态的代码可能会失败。

好吧,一个肯定但又丑陋的方法是在你的班级上设一个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只是最后尝试捕获的糖。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM