…because it looks like I just ran into a bug. A compiler bug. A while back I posted about Assert.ExpectedException, and how that style of exception testing is an improvement over the ExpectedException style. Here’s the code as a reminder:
public static void Throws<ExceptionType>(Action blockToExecute) where ExceptionType : SystemException { try { blockToExecute(); } catch (ExceptionType) { return; } catch (Exception ex) { Assert.Fail("Expected exception of type " + typeof(ExceptionType) + " but type of " + ex.GetType() + " was thrown instead."); } Assert.Fail("Expected exception of type " + typeof(ExceptionType) + " but no exception was thrown."); }Simple, right?
Not exactly. One would think that the following test would pass:
[TestMethod] public void SimpleTest() { int[] tmp = new int[] { 0, 1, 2, 3 }; MyAssert.Throws<IndexOutOfRangeException>(() => { tmp[100] = 100; }); }Strangely, this fails with the following error message:"Assert.Fail failed. Expected exception of type System.IndexOutOfRangeException but type of System.IndexOutOfRangeException was thrown instead."
What? Stepping through the code did no good either. A runtime check in the immediate window showed that the type of the exception actually did match the type of the generic parameter. In other words, this returned true at runtime:
ex.GetType() == typeof(exceptionType)Baffling. A look at the IL code via Reflector with resident C# guru Bill Wagner turned up nothing suspicious. Oddly enough, commenting out the final catch caused my simple test to pass.
The only solution we had was that this must be a JITer bug…and not the dancing kind! *groan*
Thoughts?
2 Comments
What about this code:
public static void Throws(Action blockToExecute) where exceptionType : SystemException
{
try
{
blockToExecute();
}
catch (Exception ex)
{
Assert.IsTrue(typeof(exceptionType) == ex.GetType(), “Expected exception of type ” + typeof(exceptionType) + ” but type of ” + ex.GetType() + ” was thrown instead.”);
}
Assert.Fail(“Expected exception of type ” + typeof(exceptionType) + ” but no exception was thrown.”);
}
It probably isn’t the best on performance but it seems to work correctly.
Sorry…missed the return; statement after the Assert.IsTrue(…).