在 MSTest 上调用异步操作时,单元测试预计会引发异常

发布于 2024-12-07 09:26:39 字数 1553 浏览 1 评论 0原文

下面的源代码是关于我的问题的示例代码片段。我预计调用异步操作时会发生异常。

单元测试

[TestMethod()]
[ExpectedException(typeof(Exception))]
public void OperateAsyncTest()
{
    //Arrange
    var testAsyncClass = new TestAsyncClass();
    //Act
    testAsyncClass.OperateAsync();
}

代码

public class TestAsyncClass
{
    public void OperateAsync()
    {
        ThreadPool.QueueUserWorkItem( obj =>{
            throw new Exception("an exception is occurred.");
        });
    }
}

但是,MsTest 无法捕获异常,因为测试线程可能与引发异常的线程不同。 这个问题如何解决?有什么想法吗?

下面的代码是我的解决方法,但它并不聪明或优雅。

解决方法

[TestClass()]
public class TestAsyncClassTest
{
    private static Exception _exception = new Exception();
    private static readonly EventWaitHandle ExceptionWaitHandle = new AutoResetEvent(false);

    static TestAsyncClassTest()
    {
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
    }

    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        _exception = (Exception)e.ExceptionObject;
        ExceptionWaitHandle.Set();
    }


    [TestMethod()]
    [ExpectedException(typeof(Exception))]
    public void OperateAsyncTest()
    {
        //Arrange
        var testAsyncClass = new TestAsyncClass();
        //Act
        lock(_exception)
        {
            testAsyncClass.OperateAsync();
            ExceptionWaitHandle.WaitOne();
            throw _exception;
        }
    }
}

The source code below is an example code snippet about my problem. I expect an exception to be occurred when an asynchronous operation is called.

Unit Test

[TestMethod()]
[ExpectedException(typeof(Exception))]
public void OperateAsyncTest()
{
    //Arrange
    var testAsyncClass = new TestAsyncClass();
    //Act
    testAsyncClass.OperateAsync();
}

Code

public class TestAsyncClass
{
    public void OperateAsync()
    {
        ThreadPool.QueueUserWorkItem( obj =>{
            throw new Exception("an exception is occurred.");
        });
    }
}

However, MsTest cannot catch the exception because probably, the test thread is different from the thread throwing the exception. How is this problem solved? Any idea?

The following code is my workaround, but it is not smart or elegant.

Workaround

[TestClass()]
public class TestAsyncClassTest
{
    private static Exception _exception = new Exception();
    private static readonly EventWaitHandle ExceptionWaitHandle = new AutoResetEvent(false);

    static TestAsyncClassTest()
    {
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
    }

    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        _exception = (Exception)e.ExceptionObject;
        ExceptionWaitHandle.Set();
    }


    [TestMethod()]
    [ExpectedException(typeof(Exception))]
    public void OperateAsyncTest()
    {
        //Arrange
        var testAsyncClass = new TestAsyncClass();
        //Act
        lock(_exception)
        {
            testAsyncClass.OperateAsync();
            ExceptionWaitHandle.WaitOne();
            throw _exception;
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我的影子我的梦 2024-12-14 09:26:39

也许您可以将异步操作实现为 Task,从 OperateAsync 返回它,然后从调用者返回 Task.Wait

Task.Wait 将“观察”异常,以便您的单元测试可以检测到它(前提是您使用 ExpectedException 属性修饰它)。

代码如下所示:

public class TestAsyncClass {

    public Task OperateAsync() {
        return Task.Factory.StartNew(
            () => {
                throw new Exception("an exception is occurred.");
            }
        );
    }

}

[TestClass]
public class TestAsyncClassTest {

    [TestMethod]
    [ExpectedException(typeof(AggregateException))]
    public void OperateAsyncTest() {
        var testAsyncClass = new TestAsyncClass();
        testAsyncClass.OperateAsync().Wait();
    }

}

请注意,您将从 Task.Wait 获得一个 AggregateException。它的 InnerException 将是您从 OperateAsync 引发的异常。

Perhaps you could implement your asynchronous operation as a Task, return it from OperateAsync and then Task.Wait from the caller?

Task.Wait will "observe" the exception so your unit test can detect it (provided you adorn it with ExpectedException attribute).

The code would look like this:

public class TestAsyncClass {

    public Task OperateAsync() {
        return Task.Factory.StartNew(
            () => {
                throw new Exception("an exception is occurred.");
            }
        );
    }

}

[TestClass]
public class TestAsyncClassTest {

    [TestMethod]
    [ExpectedException(typeof(AggregateException))]
    public void OperateAsyncTest() {
        var testAsyncClass = new TestAsyncClass();
        testAsyncClass.OperateAsync().Wait();
    }

}

Note that you'll get an AggregateException from the Task.Wait. Its InnerException will be the exception you threw from OperateAsync.

日记撕了你也走了 2024-12-14 09:26:39

异常发生在不同的线程上,必须进行相应的处理。有几种选择。请查看这两篇文章:

The exception occurs on a different thread and has to be handled accordingly. There are a few options. Please take a look at these two posts:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文