单元测试 .NET 事件调用

本文关键字:调用 事件 NET 单元测试 | 更新日期: 2023-09-27 17:56:32

我有一个静态类,它环绕 .NET 事件,如 UnhandledExceptionProcessExit(CurrentAppDomain 对象的),因此当调用者在类上调用 Initialize 时,它会为这些事件订阅我自己的处理程序,稍后调用者可以使用专用 API 添加自己的处理程序方法。(它是这样设计的,所以我能够在触发事件后控制处理程序的执行顺序)。

我的问题是:是否可以对这样的类进行单元测试?

例如,我想知道当抛出未处理的异常时,我的私有处理程序已执行。 问题是,当我抛出未经处理的异常时,这将是测试的"结果"(如果我错了,请纠正我)。如果我退出该过程,也会发生相同的情况。

我在想一个可能的解决方案可能涉及加载一个新的应用程序域,尽管我不知道这是否可能以及如何在技术上解决这个问题。

单元测试 .NET 事件调用

要测试UnhandledException,您可以在新线程中抛出异常:

[TestMethod]
public void UnhandledTest()
{
    using (var okEvent = new ManualResetEventSlim())
    using (var notOkEvent = new ManualResetEventSlim())
    {
        UnhandledExceptionEventHandler handler = (o, e) =>
            {
                if (e.ExceptionObject is ApplicationException)
                    okEvent.Set();
                else notOkEvent.Set();
            };
        AppDomain.CurrentDomain.UnhandledException += handler;
        var thread = new Thread(() => { throw new ApplicationException(); });
        thread.Start();
        var result = EventWaitHandle.WaitAny(new[] { notOkEvent.WaitHandle, okEvent.WaitHandle }, 10000);
        Assert.AreEqual(1, result);
        AppDomain.CurrentDomain.UnhandledException -= handler;
    }
}

这不会导致测试失败,因为测试框架仅在执行测试方法的线程上捕获异常。

另一方面,当当前进程退出时,ProcessExit将被提出,因此测试框架很可能在那时已经关闭。因此,您必须在不同的进程中运行实际的测试代码。从单元测试方法开始,您将开始一个新的过程,它将运行测试的实质,并将测试结果传达回原始进程中的单元测试方法。

新流程只是一个单独的.exe项目。它所做的是附加到ProcessExit,停止自身,并在ProcessExit处理程序中检查一切是否正常,然后将结果传达回运行单元测试方法的进程。

您可以使用命令行进行从单元测试项目到 .exe 项目的通信,并使用某种 IPC(如临时文件或命名事件)进行通信。