针对特定exception的unit testing异步方法
有没有人有一个如何在Windows 8 Metro应用程序中unit testing异步方法的示例,以确保它抛出所需的exception?
给定一个具有异步方法的类
public static class AsyncMathsStatic { private const int DELAY = 500; public static async Task Divide(int A, int B) { await Task.Delay(DELAY); if (B == 0) throw new DivideByZeroException(); else return A / B; } }
我想使用新的Async.ExpectsException构造编写测试方法。 我试过了 :-
[TestMethod] public void DivideTest1() { Assert.ThrowsException(async () => { int Result = await AsyncMathsStatic.Divide(4, 0); }); }
但是当然测试不等待异步方法完成,因此导致测试失败,但没有抛出exception。
您可以使用与常规ExpectedExceptionAttribute
的async Task
unit testing:
[TestMethod] [ExpectedException(typeof(DivideByZeroException))] public async Task DivideTest1() { int Result = await AsyncMathsStatic.Divide(4, 0); }
从评论更新: Win8unit testing项目中的ExpectedExceptionAttribute
已替换为Assert.ThrowsException
,这是一个很好的未记录的AFAICT。 这在设计方面是一个很好的改变 ,但我不知道为什么它只在Win8上得到支持。
好吧,假设没有async
兼容的Assert.ThrowsException
(由于缺少文档而无法判断是否存在),您可以自己构建一个:
public static class AssertEx { public async Task ThrowsExceptionAsync(Func code) { try { await code(); } catch (Exception ex) { if (ex.GetType() == typeof(TException)) return; throw new AssertFailedException("Incorrect type; expected ... got ...", ex); } throw new AssertFailedException("Did not see expected exception ..."); } }
然后使用它:
[TestMethod] public async Task DivideTest1() { await AssertEx.ThrowsException(async () => { int Result = await AsyncMathsStatic.Divide(4, 0); }); }
请注意,我的示例只是对exception类型进行精确检查; 您可能也希望允许后代类型。
更新2012-11-29:打开UserVoice建议 ,将其添加到Visual Studio。
[TestMethod] public void DivideTest1() { Func action = async () => { int Result = await AsyncMathsStatic.Divide(4, 0); }); action.ShouldThrow(); }
使用.ShouldThrow()
nuget包适合我
几天前我遇到了类似的问题,并最终创造了类似于斯蒂芬上面的回答。 它可以作为一个要点 。 希望它有所帮助 – github要点有完整的代码和示例用法。
/// /// Async Asserts use with Microsoft.VisualStudio.TestPlatform.UnitTestFramework /// public static class AsyncAsserts { /// /// Verifies that an exception of type is thrown when async is executed. /// The assertion fails if no exception is thrown /// /// The generic exception which is expected to be thrown /// The async Func which is expected to throw an exception /// The task object representing the asynchronous operation. public static async Task ThrowsException (Func func) where T : Exception { return await ThrowsException(func, null); } /// /// Verifies that an exception of type is thrown when async is executed. /// The assertion fails if no exception is thrown /// /// The generic exception which is expected to be thrown /// The async Func which is expected to throw an exception /// A message to display if the assertion fails. This message can be seen in the unit test results. /// The task object representing the asynchronous operation. public static async Task ThrowsException (Func func, string message) where T : Exception { if (func == null) { throw new ArgumentNullException("func"); } string failureMessage; try { await func(); } catch (Exception exception) { if (!typeof(T).Equals(exception.GetType())) { // "Threw exception {2}, but exception {1} was expected. {0}\nException Message: {3}\nStack Trace: {4}" failureMessage = string.Format( CultureInfo.CurrentCulture, FrameworkMessages.WrongExceptionThrown, message ?? string.Empty, typeof(T), exception.GetType().Name, exception.Message, exception.StackTrace); Fail(failureMessage); } else { return (T)exception; } } // "No exception thrown. {1} exception was expected. {0}" failureMessage = string.Format( CultureInfo.CurrentCulture, FrameworkMessages.NoExceptionThrown, message ?? string.Empty, typeof(T)); Fail(failureMessage); return default(T); } private static void Fail(string message, [CallerMemberName] string assertionName = null) { string failureMessage = string.Format( CultureInfo.CurrentCulture, FrameworkMessages.AssertionFailed, assertionName, message); throw new AssertFailedException(failureMessage); } }
自Visual Studio 2012 Update 2中添加了对在 ThrowsException
方法中使用异步lambdas的支持,但仅适用于Windowsapp store测试项目。
一个问题是你需要使用Microsoft.VisualStudio.TestPlatform.UnitTestFramework.AppContainer.Assert
类来调用ThrowsException
。
因此,要使用新的ThrowsException方法,您可以执行以下操作:
using AsyncAssert = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.AppContainer.Assert; [TestMethod] public void DivideTest1() { AsyncAssert.ThrowsException(async () => { int Result = await AsyncMathsStatic.Divide(4, 0); }); }