1

Example:

Assert.AreEqual(**null**, Program.nDaysMonth(5, -10), "Error nDaysMonth, Month may -10.");

I expect a exception. How I can expect a exception in Assert.AreEqual?

Thanks.

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Jesús
  • 13
  • 4
  • 2
    If you expect an exception, why use `Assert`? Why not decorate your method with `ExpectedException`? – Yuval Itzchakov May 19 '15 at 13:46
  • See: http://stackoverflow.com/questions/933613/how-do-i-use-assert-to-verify-that-an-exception-has-been-thrown - if that doesn't fulfil your needs add extra info on why not. – tolanj May 19 '15 at 13:46
  • Are you asking how to write a unit test to verify that `Program.nDaysMonth(5, -10)` throws an exception? – juharr May 19 '15 at 13:46
  • @YuvalItzchakov you shouldnt use ExpectedException attribute, its not nice. Instead of this use Assert.Throws method. Then you know exactly where the exception occurred and the test is written better. – Pawel Maga May 19 '15 at 13:50
  • Please specify the unit test framework you're using - we can't tell that just from your code snippet. – Jon Skeet May 19 '15 at 13:52

2 Answers2

6

You don't use Assert.AreEqual, you use Assert.Throws:

Assert.Throws<ArgumentOutOfRangeException>(() => Program.nDaysMonth(5, -10));

This checks that the correct exception is thrown. If you want to add more assertions, you can use the return value:

var exception = Assert.Throws<ArgumentOutOfRangeException>(...);
Assert.AreEqual("Foo", exception.Message); // Or whatever

This works in at least NUnit and xUnit; if you're using a different testing framework you should look for similar functionality. If it doesn't exist, I'd recommend implementing it yourself - it's easy enough to do, and much cleaner than the alternatives (a try/catch block, or a method-wide ExpectedException attribute). Alternatively, change unit test framework if you can...

I'd also strongly advise you to start following the normal .NET naming conventions - nDaysMonth is not a good method name...

Some frameworks support decorating the method with an [ExpectedException] attribute - I would recommend against using that:

  1. That makes the test unclear about where you expect the exception to be thrown.
  2. If the exception is thrown elsewhere in the test method (i.e. your code is broken) the test will still pass.
  3. You can't do anything else after the exception is thrown.
  4. You can't check anything else about the exception.
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    [`Assert`](https://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.assert.aspx) doesn't have a method called `Throws`. Or am i missing something? – Yuval Itzchakov May 19 '15 at 13:50
  • 2
    @oleksii: 1) That makes the test unclear about where you expect the exception to be thrown. 2) If the exception is thrown elsewhere in the test method (i.e. your code is broken) the test will still pass. 3) You can't do anything else after the exception is thrown. 4) You can't check anything else about the exception. Basically, it's a bad idea. – Jon Skeet May 19 '15 at 13:51
  • @YuvalItzchakov: There's no single `Assert` class for unit testing - there's the one in NUnit, the one in xUnit, the one in Microsoft Test, etc. – Jon Skeet May 19 '15 at 13:52
  • @YuvalItzchakov: I have been explicit about that in the answer. – Jon Skeet May 19 '15 at 13:56
  • @oleksii: I think it's generally a good idea to *suggest* that sort of change in a comment rather than making it yourself - in this case it conflicted with one of my own edits. Fixed it all up now though. – Jon Skeet May 19 '15 at 14:00
  • Thanks. I did it with [ExpectedException]. Sorry for the method name, Im Spanish and did bad the translate. – Jesús May 19 '15 at 14:19
  • 2
    @Jesús: Did you read my reasons why using `ExpectedException` is a bad idea? – Jon Skeet May 19 '15 at 14:20
0

If you are using the Microsoft test framework, you would need to decorate the method with the ExpectedExceptionAttribute:

[TestClass]
public class UnitTest1
{
    [TestMethod]
    [ExpectedException(typeof(ArgumentOutOfRangeException))]
    public void TestMethod1()
    {
        //Do whatever causes the exception here
    }
}

The test will then pass or fail depending on the exception being thrown or not.

However, as Jon notes below, please find a test framework that supports Assert.Throws or some variation there-of. Decorating with the expected exception can cause false passes or other issues in code depending on what you are doing, and it makes it difficult to do anything after the exception is thrown in the method. Using a full-featured framework will improve the quality of your tests dramatically.

I recommend NUnit, http://www.nunit.org/

Or there are others like XUnit https://github.com/xunit/xunit

or literally dozens of others: http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#.NET_programming_languages

Ron Beyer
  • 11,003
  • 1
  • 19
  • 37
  • That's a bad idea (IMO) for the reasons listed in a comment in my answer. Limiting the scope of the expected exception to a lambda expression is *much* cleaner IMO. – Jon Skeet May 19 '15 at 13:51
  • I agree, however without rolling your own and just using what is available (for quick tests) with MS, its about the only option. Its important if its used that it be the *only* test being done in the method for clarity in my opinion. – Ron Beyer May 19 '15 at 13:52
  • It's hardly the case that you *need* to decorate the method with the attribute then, is it? That's just if you can't be bothered to reimplement `Assert.Throws` - which is pretty simple, and makes all the rest of your tests clearer, IMO. I would definitely recommend doing that (or switching to a test framework that isn't stuck in the past...) – Jon Skeet May 19 '15 at 13:54
  • Thanks. I did it with [ExpectedException]. – Jesús May 19 '15 at 14:19