ExpectedException attribute in Visual Studio 2008 and Visual Studio 2010
Today I tried to write my first unit tests under Visual Studio 2010. Just to see if Visual Studio testing system can now also be used for unit tests. Visual Studio 2008 had some annoying problems with test and I preferred to use nUnit instead. Visual Studio 2010 brings some good news – tests work. Take a look at my example.
Problems with tests under Visual Studio 2008
Visual Studio 2008 tests are problematic because they are not able to handle System.Exception as expected exception. Okay, I know the background, System.SystemException should be base class for fatal system exceptions and System.ApplicationException should be base class for non-fatal application exceptions. But this works only somewhere we don’t belong – the ideal world. Applications still throw System.Exception and also .Net Framework classes throw it.
Here is example of failing test. Notice that ExpectedException sais that System.Exception is expected when test is run.
[TestMethod]
[ExpectedException(typeof(Exception))]
public void ThisTestFails()
{
throw new Exception("This test fails!");
}
And here you can see the result.
Test fails with error message: UTA017: TestProject1.UnitTest1.ThisTestFails has invalid ExpectedException attribute. The type must inherit from Exception. I handle this situation as bug in Visual Studio because this limitation is pointless – System.Exception is not abstract class.
Every bad thing usually has its good side too. Under these limited conditions one can avoid the amount of hack-tests low by throwing correct exceptions in his or her code. If something is null that should have value then instead of System.Exception it is good idea to throw System.ArgumentNullException etc.
Visual Studio 2008 tests hack
There are two hacks to solve this issue. First hack has same structure as code above. We just change the type of exception we expect and in test we throw exception using correct type.
[TestMethod]
[ExpectedException(typeof(ApplicationException))]
public void ThisTestChangesExceptionType()
{
try
{
throw new Exception("This test passes!");
}
catch (Exception ex)
{
throw new ApplicationException(ex.Message, ex);
}
}
Our second hack is simpler. Instead of using ExpectedException attribute we assert the type of exception.
[TestMethod]
public void ThisTestUsesAssert()
{
try
{
throw new Exception("This test passes!");
}
catch (Exception ex)
{
Assert.IsTrue(ex.GetType() == typeof(Exception));
}
}
Now we get nice output for these tests as shown on following screenshot.
Both versions of this test passed well. Although these solutions are not very nice they work.
Visual Studio 2010 tests
Visual Studio 2010 handles the first test correctly. Here is the code of my test.
[TestMethod]
[ExpectedException(typeof(Exception))]
public void ThisTestExpectsException()
{
throw new Exception("Visual Studio 2010 rocks!");
}
And here is the screenshot with test result.
As we can see Visual Studio 2010 has this issue fixed and we can write also tests that expect System.Exception to be thrown. Happy testing!
I don’t understand. It’s not broken technically because now we can expect System.Exception to be thrown somewhere in a test.
But it’s still broken because the paradigm of expecting an exception **somewhere** in the test is shoddy validation. Your hack #2 seems like a better way to go — more like Assert.Throws(). That way you are validating which piece of code is throwing the exception you’re looking for.
In VS2010 everything works as expected. But is bug on Visual Studio 2008. I cannot name it differently because there is possibility that .Net Framework or some third-party library throws System.Exception. Yes, also .Net Framework classes are able to throw System.Exception. That’s why it is weird that even .Net Framework 3.5 SP1 didn’t fixed this issue.