在C#单元测试中实现未处理异常处理程序

4

我有一些测试需要依赖于一些无法修改的共享代码。这些共享代码有时会抛出异常,我希望能够处理所有未捕获的该异常实例,而不必在调用每个共享代码时都用try catch包装一遍(这里有多年的测试)。

同时,我也想要能够重新抛出非我所需类型的异常。

我已经尝试过:

public void init() 
{
    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    Logger.Info("Caught exception");
    throw (Exception)e.ExceptionObject;
}

但是似乎股票单元测试框架(Microsoft.VisualStudio.QualityTools.UnitTestsFramework)正在处理AppDomain并阻止我替换其UnhandledException处理程序,或者我只是没有理解单元测试框架如何处理AppDomain(很有可能)。 有人有什么建议吗?

如果第三方代码在您的测试期间引发未处理的异常,那么这个异常肯定应该允许影响您的测试结果。为什么要处理这个异常? - John Saunders
1
这些异常是在测试过程中发生的吗?如果是的话,大多数单元测试框架会在运行测试时捕获异常(以报告异常),在它到达未处理异常处理程序之前。 - Dan Bryant
@JohnSaunders,我确实理解在大多数情况下我不想处理这个异常,但是这些测试有一个非常复杂的设置过程,原因很可能在于设置。如果我可以处理异常,那么我就可以重新设置环境,或许可以挽救测试。我知道这很糟糕,但这是必要的,也是它们的复杂性所带来的。 - Reuben Tanner
@DanBryant,我明白了,那很有道理。 - Reuben Tanner
对于这个问题的未来观众,当我说设置过程对于这些测试来说是“非常复杂”的时候,我的意思是_非常_复杂:启动虚拟处理器,加载测试资料,开始多个交互进程……它们肯定超出了单元测试的范畴,但我们使用框架来运行它们。 - Reuben Tanner
2个回答

2
尝试订阅AppDomain.CurrentDomain.FirstChanceException事件。根据微软的文档:
当托管代码中抛出异常时,在运行时在应用程序域中搜索异常处理程序之前会发生此事件。
换句话说,你可以在单元测试框架捕获之前就捕获它。更多信息请参见此处

1

很遗憾,这需要一个解决方法,但以下是我的解决方案。我们在应用程序中使用未处理的异常处理程序来处理某些错误。不幸的是,在单元测试期间,测试框架吞噬了未处理的异常。

using System;
using Xunit;
using System.Threading;

public class MyTests : IDisposable
{
    private UnhandledExceptionEventArgs _unhandledException = null;
    public MyTests()
    {
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
    }

    public void Dispose()
    {
        Assert.Null(_unhandledException);
    }

    private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        _unhandledException = e;
    }

    //Example from : https://github.com/xunit/xunit/issues/157
    [Fact]
    public void TestExceptionInBackgroundThread()
    {
        Thread t = new Thread(() =>
        {
            throw new InvalidOperationException();
        });
        t.Start();
        t.Join();
    }
}

output


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接