如何检查是否已引发异常

本文关键字:异常 是否 何检查 检查 | 更新日期: 2023-09-27 18:24:53

我正在为一项服务进行一些测试自动化,并找到了一种巧妙的方法来汇总一些常见的设置&验证为"会话"类。

从概念上讲,测试用例可能是这样的:

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对象构造函数中,我通过每个角色的正确身份验证等设置了与正在测试的服务的连接,在Session Dispose()方法中,我有一个通用的验证块,例如,它检查在会话生存期内是否没有引发服务器端错误或警告。

当然,这有点滥用IDispose模式,如果using块内的测试代码抛出异常and验证块也抛出异常,则第二个异常将屏蔽第一个异常。

从概念上讲,如果我们有这样的场景:

using (var managerSession = new Session(managerRole))
{
    Assert.IsTrue(managerSession.DoJob(), "Manager did not do his job");
}

如果assert失败,或者调用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方法能够在替换之前封装挂起的异常,那将是很有帮助的。不幸的是,不存在这样的功能,我不希望添加任何功能。

虽然有一些技巧可以用来达到预期的效果,但唯一语义正确的方法是将异常作为Dispose方法的参数。任何其他方法的问题是,Dispose可能从多个嵌套的finally块中运行,其中一些块具有挂起的异常,而另一些块没有;检查执行上下文以确定嵌套最深的CCD_ 12块的状态的代码可能会失败。

好吧,一个肯定但丑陋的方法是在类上使用bool(默认值为false)。

using (var managerSession = new Session(managerRole))
{
    Assert.IsTrue(managerSession.DoJob(), "Manager did not do his job");
    managerSession.NoExceptionThrown = true;
}

我认为你的IDisposable模式不会比这更干净。

在这种情况下,尝试。。。接住finally可能会更好地工作,因为您可以直接访问异常对象,您可以测试该对象是否为null(这是一个单词吗?),甚至可能存储它以备将来使用。你不应该失去任何东西,因为using只是最后一次尝试接球的糖。