ExceptionAsserts & debugging your C# project in VS
We've been using NUnit & VisualStudio to write C# .NET code for a while now. Testing Exceptions was done in the style of
old syntax:
[Test]
[ExpectException(typeof(ExceptionType))]
public void TestExceptionType()
{
}
Now NUnit has released version 2.5.2 which introduced Assert.Throws( Type expectedExceptionType, TestDelegate code );
This makes exception testing a whole lot more flexible. Our exception tests now look like this:
new syntax:
[Test]
public void TestWithNullBuff开发者_JAVA百科erArgument()
{
ArgumentNullException ex = Assert.Throws<ArgumentNullException>(() => _testInstance.TestFunction(null));
// now you can examine the exception and it's properties
Assert.AreEqual(ex.Message, "Argument was null");
}
Our problem is that if Assert.Throws is used Visual Studio will cough up a window showing an unhandled exception when NUnit (either console or GUI runner) is used to debug the program.
to clarify this: we've set the VS project containing the unit tests to run nunit-x86.exe when debugging. (See project properties, debugging tab, start action is set to run nunit-x86.exe)
This stops NUnit from continuing the tests. It is possible to continue debugging/unit testing by pressing F5 but this is not a viable solution.
Is there any way to avoid this? Putting a try...catch block around the Assert.Throws does nothing since the exception happens in the delegate code.
I hope someone can shed some light on this.
The problem itself appears because most likely you have option Enable Just My Code turned on (Tools->Options->Debugging->General->Enable Just My Code).
"When this feature is enabled, the debugger displays and steps into user code ("My Code") only, ignoring system code and other code that is optimized or does not have debugging symbols" (see "General, Debugging, Options Dialog Box")
Normally you have a release version of nunit.framework.dll which does not have a corresponding nunit.framework.pdb file.
So there are 2 options:
Disable "Just My Code" feature
Download sources of nunit (from http://www.nunit.org/index.php?p=download), build them in debug mode, put all nunit.framework.* (dll, pdb, xml) into lib or other directory in your solution and reference that nunit.framework.dll in your test project.
Hope this helps.
The same problem also annoyed me for quite some time, I did a few tests and found the following:
If a library (nunit in this case) is compiled with debug info set to 'none', then if construct similar to one below is executed withing the library and delegate's code throws an exception, then VS stops complaining about exception not handled by the user code.
Library code:
public static Exception Throws(TestDelegate code, string message)
{
Exception caughtException = null;
try
{
code();
}
catch (Exception ex)
{
caughtException = ex;
}
return caughtException;
}
Client code:
private void btnTest_Click(object sender, EventArgs e)
{
var ex = MyAssert.Throws(() => { throw new Exception(); }, "");
}
Setting debug info of a library project to any other option other than 'none' resolves the problem i.e. debugger does not stop anymore on those kinda "unhandled" exceptions. I tested it with nunit and my own hand-rolled library with the above code (took a snippet from nunit's Throws method). I suppose it is a feature or a "feature" of VS.
It leaves us with not so many options:
Filter exception as previously suggested
Recompile nunit.framework.dll for local use, to avoid those annoying stops
Other options could be to contact either MS or NUnit teams or both and ask them to investigate/clarify issue and compile NUnit with minimal level of debugging info respectevily.
Edit:
Found one more option.
- In my case unchecking 'Suppress JIT optimization on module load' also does the trick, even if libraries compiled with no debug info. However it only works when project is run in release configuration.
I think you are being blinded by the NUnit assertion. You could achieve the same thing with a simple try/catch.
try
{
_testInstance.TestFunction(null);
Assert.Fail("The method should have thrown...");
}catch{}
Now, you have everything you need. You fail if the exception isn't thrown and your regular code can handle exceptions as expected.
Could it be achievable by disabling the Exception. Open Debug/Exceptions menu , and search for your Exception.
精彩评论