here's my problem.
I have the following unit test:
[Test]
public void ShouldParseXaml()
{
try
{
XamlServices.Load("Filel.xaml");
}
catch (Exception e)
{
Assert.Fail(e.Message);
}
}
When this unit test is run automatically via a GUI test runner, I get the following exception message:
Add value to dictionary of type 'System.Collections.Generic.Dictionary(System.UInt32,
System.Collections.Generic.List(MyXamlFramework.IConfigurationFieldNameProvider))'
threw an exception.
at NUnit.Framework.Assert.Fail(String message, Object[] args)
at NUnit.Framework.Assert.Fail(String message)
at XamlBehaviour.ShouldParseXaml3() in C:\test\XamlBehaviour.cs:line 62#0
If however, I place a breakpoint on the Assert.Fail(e.Message) and then continue to let the test run after it breaks, I get following exception message:
'Add value to dictionary of type 'System.Collections.Generic.Dictionary(System.UInt32,
System.Collections.Generic.List(MyXamlFramework.IConfigurationFieldNameProvider))'
threw an exception.' Line number '70' and line position '11'.
at NUnit.Framework.Assert.Fail(String message, Object[] args)
at NUnit.Framework.Assert.Fail(String message)
at XamlBehaviour.ShouldParseXaml3() in C:\test\XamlBehaviour.cs:line 62#0
If possible, I'd really like to retain the full exception message which includes the line and position number when the test is auto run.
Thanks for your help.
Related
I am using Timeout attribute for nunit test case as below:
[Test, TestCaseSource("TestCases"), Retry(2), Timeout(10000)
public void test(){
// Some code that runs for more than 10 seconds
}
I have gone through the documentation of nunit but it said that apart from assertion error, retry will not work but I have a situation where test times out.
I want this test to execute again as it is timing out but it executes only once using above code. Please help.
We had the same issue (E2E UI testing, which is finicky so test throws exceptions and retry doesnt work)
You can do a workaround and wrap your test code IE
protected void ExecuteTest(Action test)
{
try
{
test();
}
catch (Exception ex)
{
//If the caught exception is not an assert exception but an unhandled exception.
if (!(ex is AssertionException))
Assert.Fail(ex.Message);
}
}
Which for a test youd want to retry even if it throws would look like
[Test, Retry(3)]
public void TestCase()
{
ExecuteTest(() =>{
<test code>
});
}
Im unsure how the nunit timeout attribute would work (Im assuming the test() call would just throw a timeout exception in which case this solution would work) but it this solution doesnt work for that you can switch to a task or action and WaitOne or something and have a default param for execute test be 1000 for your timeout IE
protected void ExecuteTest(Action test, int timeoutSeconds = 10)
{
try
{
var task = Task.Run(test);
if (!task.Wait(TimeSpan.FromSeconds(timeoutSeconds)))
throw new TimeoutException("Timed out");
test.BeginInvoke(null,null);
}
catch (Exception ex)
{
//If the caught exception is not an assert exception but an unhandled exception.
if (!(ex is AssertionException))
Assert.Fail(ex.Message);
}
}
This looked like our best solution so it's what we currently have implemented and seems to work fine
I'm having a problem logging my exceptions using this piece of code:
Logger.logger.Error("Exception occured", ex, "");
because it only logs the message but when I use the same function with 2 arguments supplied in it then it will work, though it is obsolete that's why I'm reluctant in using it.
This is the piece of code that is working and i'm currently using:
Logger.logger.Error("Exception occured", ex);
Any help would be appreciated. Thanks!
seems like you mistook parameters order. An exception should be first, second is a message
From NLog sources
public void Error(Exception exception, [Localizable(false)] string message)
public void Error(Exception exception, [Localizable(false)] string message, params object[] args)
NLog changed the functions.
In some older Version you had:
_logger.ErrorException("My Message", myException);
Now the first param ist of Type Exception:
_logger.Error(myException, "My Message: {0}", myException.Message);
..ErrorException() is now obsolete..
I have an application that can sometimes throw an exception, most of these are handled but I want the unhandled ones to be recoverable. So I'm trying to invoke the method that caused the exception by using the exception's targetsite like so:
Exception ex = Global.ThrownException;
MethodBase mB = ex.TargetSite;
try
{
mB.Invoke(mB, null);
}
catch(Exception exc)
{
System.Windows.MessageBox.Show(exc.Message);
}
I'm doing this to make sure that the exception was a one time error before showing the window to the user again.
The test method (and the exception targetsite) I'm trying to invoke is this:
public void testMethod()
{
throw new System.IO.IOException("test");
}
When I run this, an exception is thrown with the message "Object does not match target type" but since testMethod doesn't have any parameters this shouldn't happen.
Any ideas?
I've a method test that does not have a clear assert expression. The returned tested value is a very long string that has to be inspected by a programmer to check if it is correct or not. For this reason, if the code executes without exceptions, I'm calling 'Assert.Inconclusive'.
However, if some kind of Exception is thrown, I want to call 'Assert.Fail' with the exception message. Something like this:
[TestMethod()]
public void Test()
{
try {
string toBeChecked = MethodToBeTested();
//the string is so particular that no clear
//assertion can be made about it.
Console.WriteLine(toBeChecked);
Assert.Inconclusive("Check the console output.");
} catch(Exception e) {
Assert.Fail(e.Message);
}
}
The problem with this code is that if no regular exception is thrown, the Assert.Inconclusive method also throws an exception that is catched, so Assert.Fail is called, and from the IDE test result pane it seems that the test has failed. This is not what I want.
Is there a way to filter the exceptions, such as catching every exception but the Assert-like ones?
(I'm using .NET framework 3.5SP1)
Why not just leave out the Assert.Inconclusive()? In fact, why catch any exceptions at all - if the code throws an exception the unit test framework will mark it as failed. Less is more:
[TestMethod()]
public void Test()
{
string toBeChecked = MethodToBeTested();
Console.WriteLine(toBeChecked);
}
But this is a poor unit test if we can not automatically check the result. All we are checking is that no exception is thrown.
Are there no asserts you can make about the resulting string?
For example, that is is not null or empty? Do we expect it to contain a certain sub-string that we can test?
At least give the test a helpful name, which includes something like: ManualAssertRequired
The Assert.Inconclusive method should throw a AssertInconclusiveException so you can either mark the Test as ExcpectedException(typeof(AssertInconclusiveExcpetion)) or use something like this:
[TestMethod()]
public void Test()
{
try {
string toBeChecked = MethodToBeTested();
//the string is so particular that no clear
//assertion can be made about it.
Console.WriteLine(toBeChecked);
Assert.Inconclusive("Check the console output.");
} catch(AsssertInconclusiveException) {
/* Do nothing */
}
} catch(Exception e) {
Assert.Fail(e.Message);
}
}
Try to catch specific exception type instead of Exception or add another catch for nunit exception that is caused by Assert.Inconclusivemethod which is AssertInconclusiveException...
For example modify it like this:
[TestMethod()]
public void Test()
{
try {
string toBeChecked = MethodToBeTested();
//the string is so particular that no clear
//assertion can be made about it.
Console.WriteLine(toBeChecked);
Assert.Inconclusive("Check the console output.");
} catch(AssertInconclusiveException e) {
// do nothing...
} catch(Exception e) {
Assert.Fail(e.Message);
}
}
I have this code
try
{
//AN EXCEPTION IS GENERATED HERE!!!
}
catch
{
SqlService.RollbackTransaction();
throw;
}
Code above is called in this code
try
{
//HERE IS CALLED THE METHOD THAT CONTAINS THE CODE ABOVE
}
catch (Exception ex)
{
HandleException(ex);
}
The exception passed as parameter to the method "HandleException" contains the line number of the "throw" line in the stack trace instead of the real line where the exception was generated. Anyone knows why this could be happening?
EDIT1
Ok, thanks to all for your answers. I changed the inner catch for
catch(Exception ex)
{
SqlService.RollbackTransaction();
throw new Exception("Enrollment error", ex);
}
Now I have the correct line on the stack trace, but I had to create a new exception. I was hoping to find a better solution :-(
EDIT2
Maybe (if you have 5 minutes) you could try this scenario in order to check if you get the same result, not very complicated to recreate.
Yes, this is a limitation in the exception handling logic. If a method contains more than one throw statement that throws an exception then you'll get the line number of the last one that threw. This example code reproduces this behavior:
using System;
class Program {
static void Main(string[] args) {
try {
Test();
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
static void Test() {
try {
throw new Exception(); // Line 15
}
catch {
throw; // Line 18
}
}
}
Output:
System.Exception: Exception of type 'System.Exception' was thrown.
at Program.Test() in ConsoleApplication1\Program.cs:line 18
at Program.Main(String[] args) in ConsoleApplication1\Program.cs:line 6
The work-around is simple, just use a helper method to run the code that might throw an exception.
Like this:
static void Test() {
try {
Test2(); // Line 15
}
catch {
throw; // Line 18
}
}
static void Test2() {
throw new Exception(); // Line 22
}
The underlying reason for this awkward behavior is that .NET exception handling is built on top of the operating system support for exceptions. Called SEH, Structured Exception Handling in Windows. Which is stack-frame based, there can only be one active exception per stack frame. A .NET method has one stack frame, regardless of the number of scope blocks inside the method. By using the helper method, you automatically get another stack frame that can track its own exception. The jitter also automatically suppresses the inlining optimization when a method contains a throw statement so there is no need to explicitly use the [MethodImpl] attribute.
"But throw; preserves the stack trace !! Use throw; "
How many times have you heard that... Well anyone who has been programming .NET for a while has almost certainly heard that and probably accepted it as the be all and end all of 'rethrowing' exceptions.
Unfortunately it's not always true. As #hans explains, if the code causing the exception occurs in the same method as the throw; statement then the stack trace gets reset to that line.
One solution is to extract the code inside the try, catch into a separate method, and another solution is to throw a new exception with the caught exception as an inner exception. A new method is slightly clumsy, and a new Exception() loses the original exception type if you attempt to catch it further up the call stack.
I found a better description of this problem was found on Fabrice Marguerie's blog.
BUT even better there's another StackOverflow question which has solutions (even if some of them involve reflection):
In C#, how can I rethrow InnerException without losing stack trace?
As of .NET Framework 4.5 you can use the ExceptionDispatchInfo class to do this without the need for another method. For example, borrowing the code from Hans' excellent answer, when you just use throw, like this:
using System;
class Program {
static void Main(string[] args) {
try {
Test();
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
static void Test() {
try {
throw new ArgumentException(); // Line 15
}
catch {
throw; // Line 18
}
}
}
It outputs this:
System.ArgumentException: Value does not fall within the expected range.
at Program.Test() in Program.cs:line 18
at Program.Main(String[] args) in Program.cs:line 6
But, you can use ExceptionDispatchInfo to capture and re-throw the exception, like this:
using System;
class Program {
static void Main(string[] args) {
try {
Test();
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
static void Test() {
try {
throw new ArgumentException(); // Line 15
}
catch(Exception ex) {
ExceptionDispatchInfo.Capture(ex).Throw(); // Line 18
}
}
}
Then it will output this:
System.ArgumentException: Value does not fall within the expected range.
at Program.Test() in Program.cs:line 15
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Program.Test() in Program.cs:line 18
at Program.Main(String[] args) in Program.cs:line 6
As you can see, ExceptionDispatchInfo.Throw appends additional information to the stack trace of the original exception, adding the fact that it was re-thrown, but it retains the original line number and exception type. See the MSDN documentation for more information.
Does the date/time stamp of your .pdb file match your .exe/.dll file? If not, it could be that the compilation is not in "debug mode" which generates a fresh .pdb file on each build. The pdb file has the accurate line numbers when exceptions occur.
Look into your compile settings to make sure the debug data is generated, or if you're in a test/production environment, check the .pdb file to make sure the timestamps match.
C# stack traces are generated at throw time, not at exception creation time.
This is different from Java, where the stack traces are filled at exception creation time.
This is apparently by design.
I often get this in production systems if Optimize code is checked.
This screws up line numbers even in 2016.
Make sure your configuration is set to 'Release' or whatever configuration you are building and deploying under. The checkbox has a different value per configuration
I never ultimately know how more 'optimized' my code is with this checked - so check it back if you need to - but it has saved my stack trace on many occasions.