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;
}
}
}
Perhaps you could implement your asynchronous operation as a
Task, return it fromOperateAsyncand thenTask.Waitfrom the caller?Task.Waitwill “observe” the exception so your unit test can detect it (provided you adorn it withExpectedExceptionattribute).The code would look like this:
Note that you’ll get an
AggregateExceptionfrom theTask.Wait. ItsInnerExceptionwill be the exception you threw fromOperateAsync.