13

Possible Duplicate:
How do I test an async method with NUnit, eventually with another framework?

What I would like to know is how I can assert that an asynchronous method throws an exception, in a C# unit test? I am able to write asynchronous unit tests with Microsoft.VisualStudio.TestTools.UnitTesting in Visual Studio 2012, but have not figured out how to test for exceptions. I know that xUnit.net also supports asynchronous test methods in this way, although I haven't tried that framework yet.

For an example of what I mean, the following code defines the system under test:

using System;
using System.Threading.Tasks;

public class AsyncClass
{
    public AsyncClass() { }

    public Task<int> GetIntAsync()
    {
        throw new NotImplementedException();
    }
}    

This code snippet defines a test TestGetIntAsync for AsyncClass.GetIntAsync. This is where I need input on how to accomplish the assertion that GetIntAsync throws an exception:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Threading.Tasks;

[TestClass]
public class TestAsyncClass
{
    [TestMethod]
    public async Task TestGetIntAsync()
    {
        var obj = new AsyncClass();
        // How do I assert that an exception is thrown?
        var rslt = await obj.GetIntAsync();
    }
}

Feel free to employ some other relevant unit test framework than the Visual Studio one, such as xUnit.net, if necessary or you would argue that it's a better option.

Community
  • 1
  • 1
aknuds1
  • 65,625
  • 67
  • 195
  • 317
  • @JonSkeet Not really, as this is specifically about checking exceptions. Although I see now it makes no difference with the Visual Studio framework. For xUnit.net, however, I'm still not sure how to do it. – aknuds1 Sep 03 '12 at 13:31
  • @JonSkeet Initially I agreed, but now I don't. If this question is correct in that Microsoft's unit testing already supports async tests, your answer to that other question doesn't really apply here. The only problem is rewriting the test in such a way that it tests for an exception. –  Sep 03 '12 at 13:31
  • @hvd: In that case it sounds like the problem has *nothing* to do with asynchrony - certainly the answers given don't really depend on the async part. – Jon Skeet Sep 03 '12 at 13:57
  • @JonSkeet Like I said, it didn't occur to me that the Visual Studio unit testing framework handles this via method attributes. I'm still wondering how to implement the same with xUnit.net, but I guess that's better left to another question... – aknuds1 Sep 03 '12 at 14:04
  • @aknuds1: I would personally strongly suggest using Assert.Throws where available instead. It limits the scope of where you expect the exception to be thrown. But my point is that the async part is a red herring - they're completely orthogonal aspects of testing in this case. – Jon Skeet Sep 03 '12 at 14:38
  • @JonSkeet How would I use Assert.Throws? It's not in the Microsoft.VisualStudio.TestTools.UnitTesting namespace? Also, apparently Assert.Throws in xUnit.net at least, must be adapted for async. – aknuds1 Sep 03 '12 at 15:32
  • @JonSkeet I forgot to include the link to the xUnit.net issue discussing support for async methods with Assert.Throws: http://xunit.codeplex.com/workitem/9799. – aknuds1 Sep 03 '12 at 19:26

4 Answers4

11

Please try mark method with:

[ExpectedException(typeof(NotImplementedException))]
petro.sidlovskyy
  • 5,075
  • 1
  • 25
  • 29
10

1st Option would be:

try
{
   await obj.GetIntAsync();
   Assert.Fail("No exception was thrown");
}
catch (NotImplementedException e)
{      
   Assert.Equal("Exception Message Text", e.Message);
}

2nd Option would be to use the Expected Exception Attribute:

[ExpectedException(typeof(NotImplementedException))]

3rd Option would be to use the Assert.Throws :

Assert.Throws<NotImplementedException>(delegate { obj.GetIntAsync(); });
CloudyMarble
  • 36,908
  • 70
  • 97
  • 130
  • What's the purpose of the `Assert.IsTrue(true)`? – svick Sep 03 '12 at 13:52
  • @svick: right! we can remove it :) – CloudyMarble Sep 03 '12 at 13:54
  • 1
    @svick Some people use an Assert.IsTrue(true) to indicate to anyone reading the code that just getting to that point in the code indicates success (without the Assert.IsTrue(true) it might look like the author forgot to put in an Assert) – Rune Nov 02 '15 at 19:48
2
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Threading.Tasks;

[TestClass]
public class TestAsyncClass
{
    [TestMethod]
    [ExpectedException(typeof(NotImplementedException))]
    public async Task TestGetIntAsync()
    {
        var obj = new AsyncClass();
        // How do I assert that an exception is thrown?
        var rslt = await obj.GetIntAsync();
    }
}
Dmytro
  • 16,668
  • 27
  • 80
  • 130
0

Try use TPL:

[ExpectedException(typeof(NotImplementedException))]
[TestMethod]
public void TestGetInt()
{
    TaskFactory.FromAsync(client.BeginGetInt, client.EndGetInt, null, null)
               .ContinueWith(result =>
                   {
                       Assert.IsNotNull(result.Exception);
                   }
}
abatishchev
  • 98,240
  • 88
  • 296
  • 433