Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing async method for specific exception

Tags:

Does anyone have an example of how to unit test an async method in a Windows 8 Metro application, to ensure that it throws the required exception?

Given a class with an async method

public static class AsyncMathsStatic {     private const int DELAY = 500;      public static async Task<int> Divide(int A, int B)     {         await Task.Delay(DELAY);         if (B == 0)             throw new DivideByZeroException();         else             return A / B;     } } 

I want to write a test method using the new Async.ExpectsException construction. I've tried :-

[TestMethod] public void DivideTest1() {     Assert.ThrowsException<DivideByZeroException>(async () => { int Result = await AsyncMathsStatic.Divide(4, 0); }); } 

but of course the test doesn't wait for the async method to complete, and so results in a failed test that the exception hasn't been thrown.

like image 596
Peregrine Avatar asked Oct 11 '12 10:10

Peregrine


2 Answers

You can use an async Task unit test with the regular ExpectedExceptionAttribute:

[TestMethod] [ExpectedException(typeof(DivideByZeroException))] public async Task DivideTest1() {   int Result = await AsyncMathsStatic.Divide(4, 0); } 

Update from comment: ExpectedExceptionAttribute on Win8 unit test projects has been replaced with Assert.ThrowsException, which is nicely undocumented AFAICT. This is a good change design-wise, but I don't know why it's only supported on Win8.

Well, assuming that there's no async-compatible Assert.ThrowsException (I can't tell if there is one or not due to lack of documentation), you could build one yourself:

public static class AssertEx {   public async Task ThrowsExceptionAsync<TException>(Func<Task> 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 ...");   } } 

and then use it as such:

[TestMethod] public async Task DivideTest1() {   await AssertEx.ThrowsException<DivideByZeroException>(async () => {        int Result = await AsyncMathsStatic.Divide(4, 0);   }); } 

Note that my example here is just doing an exact check for the exception type; you may prefer to allow descendant types as well.

Update 2012-11-29: Opened a UserVoice suggestion to add this to Visual Studio.

like image 57
Stephen Cleary Avatar answered Oct 15 '22 03:10

Stephen Cleary


[TestMethod] public void DivideTest1() {     Func<Task> action = async () => { int Result = await AsyncMathsStatic.Divide(4, 0); });     action.ShouldThrow<DivideByZeroException>(); } 

Using .ShouldThrow() from FluentAssertions nuget package works for me

like image 27
msrc Avatar answered Oct 15 '22 05:10

msrc