I'm working on selenium with C# and using NUnit3.0 test framework and I need to implement a global exception handler in my test project, how to do it? any help appreciated.
You can create you own Custom exceptions like this:
public class CustomSeleniumException: Exception
{
public CustomSeleniumException()
{
}
public CustomSeleniumException(string message)
: base(message)
{
}
public CustomSeleniumException(string message, Exception inner)
: base(message, inner)
{
}
}
I'm not sure what you mean by
global exception handler
but MSDN gives basic guide here. IMHO having central place to manage thrown exceptions could be a bad idea. Exceptions are thrown in a certain scope and you need to catch those according to your flow. Sometimes you need to let Exceptions propagate higher up the call chain, rather than handling them right away. You could look at those Exception patterns before making the final decision. But if you still need such, try this Global Exception Handler.
Related
I just started on a rather extensive automation project that uses MS's UnitTestFramework. One thing I noticed is that when there's an error in my code - not the app I test - the framework catches that error and fails the test in a nice happy way that allows for the test iteration to complete. However, I want to be able to see those exceptions & stack trace in my log4net logs, and so far I have found no way to grab them in my test cleanup (or anywhere outside of a try catch block which I have no intention of splattering in every method).
Anyone know how to get these exceptions into my logs?
You could use First-Chance Exception Notifications
via the AppDomain.FirstChanceException Event -
This event is only a notification. Handling this event does not handle
the exception or affect subsequent exception handling in any way.
After the event has been raised and event handlers have been invoked,
the common language runtime (CLR) begins to search for a handler for
the exception. FirstChanceException provides the application domain
with a first chance to examine any managed exception.
So something like this (note it is in a method marked as AssemblyInitialize, which means it runs once per test run, and the code is excluding the AssertFailedException thrown by MSTest when a test fails. You might want to exclude other exceptions as well, as otherwise there could be a lot of 'noise' in the logs.)
[TestClass]
public class Initialize
{
[AssemblyInitialize]
public static void InitializeLogging(TestContext testContext)
{
AppDomain.CurrentDomain.FirstChanceException += (source, e) =>
{
if (e.Exception is AssertFailedException == false)
LogManager.GetLogger("TestExceptions").Error(e.Exception);
};
}
}
If it feasible for you to replace the [TestMethod] attribute then you can define your own attribute MyTestMethod, say, by deriving from the default one like this:
public class MyTestMethodAttribute : TestMethodAttribute
{
public override TestResult[] Execute(ITestMethod testMethod)
{
TestResult[] testResults = base.Execute(testMethod);
foreach (var testResult in testResults.Where(e => e.Outcome == UnitTestOutcome.Failed))
testResult.LogOutput += $"Exception `{testResult.TestFailureException.GetType().Name}` with message `{testResult.TestFailureException.Message}`.";
return testResults;
}
}
The following test then produces the expected log message Exception TestFailedException with message Assert.Fail failed. Some exception text. in the standard output panel of Visual Studio's Test Explorer.
[TestClass]
public class Tests
{
[MyTestMethod]
public void Test()
=> Assert.Fail("Some exception text");
}
The approach also works when tests execute in parallel.
I have a static class that retrieves values from app.config in its constructor. These could potentially be null, and I would like to throw an exception if this is the case.
I would like to throw the error in the static methods that use these values, but ArgumentNullException doesn't seem right as they are not arguments passed to the method.
Is there an alternative, or is this not a good approach?
It does not matter what you throw. It is not an exception that should ever be caught, catching it does not fix the .config file. Using a custom exception type only encourages a bad practice.
So don't, just throw Exception. Be sure to tell the reader what is wrong with the .config file, that's the only thing he needs to know. And that he can read it, write an event handler for AppDomain.CurrentDomain.UnhandledException
You can create your own custom exception (MSDN).
Basically:
public class ConfigurationValueMissingException : Exception
{
public ConfigurationValueMissingException()
{
}
public ConfigurationValueMissingException(string message)
: base(message)
{
}
public ConfigurationValueMissingException(string message, Exception inner)
: base(message, inner)
{
}
}
Why? If you follow Microsoft Code Analysis rules, you can't simply throw new Exception(); as that would be a violation of CA2201: Do not raise reserved exception types:
Do Not Throw General Exceptions
If you throw a general exception type, such as Exception or
SystemException in a library or framework, it forces consumers to
catch all exceptions, including unknown exceptions that they do not
know how to handle.
Instead, either throw a more derived type that already exists in the
framework, or create your own type that derives from Exception.
How to Fix Violations
To fix a violation of this rule, change the type of the thrown exception to a specific type that is not one of the reserved types.
When to Suppress Warnings
Do not suppress a warning from this rule.
This would be a custom exception that fully passes Code Analysis rules:
using System;
using System.Runtime.Serialization;
[Serializable]
public class ConfigurationValueMissingException : Exception
{
public ConfigurationValueMissingException()
{
}
public ConfigurationValueMissingException(string message)
: base(message)
{
}
public ConfigurationValueMissingException(string message, Exception inner)
: base(message, inner)
{
}
protected ConfigurationValueMissingException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
You can use any of the System.Configuration namespace exceptions. Or create your own ConfigurationParameterNullException
Create a class that inherits from Exception:
https://msdn.microsoft.com/en-us/library/87cdya3t(v=vs.110).aspx
public class NullConfigEntryException: Exception
And then throw a NullConfigEntryException when you find an empty one
A custom exception is the most informative, and you have control over what information it includes. A more generic approach is to use ApplicationException (the most generic being Exception). If you take the generic approach, be sure to add details in Message, Data, etc.
I am handling errors using IErrorHandler in WCF REST. I need to log class name, method name, line number, error code etc. and i find out the soultions to all this.
But I am thinking any possibility or options to get 1ErrorLevel1 like windows event viewer. Eg: Warning, Information, Error.
Actually if I do like this my applciation exceptions can be put as Information. This can be work simple create an custom Exception class.
But my question is for other exceptions (other than my application exceptions) any option to get this level based on the error. I don't need to set this level for other types of erros.
Actually i am logging the exception in HandleError event. Now i am just throw my exceptions as applicationexception.
Just see my Service method code below:
if(!long.TryParse("534543534", out value))
{
throw new ApplicationException("Input is Not Valid!!!");
}
So in my error handling i got this as application exception. Here i dont knwo this is because of FormatException, Overflow Exception, ArgumentNullException. How i handle this. I can add the original exception as innerexception but need to wrap try..catch in each service method to get the exception. Is this good practice when i have the IErrorHandler methods. Please suggest good approach for this
In .NET, an exception is a severe error that interrupts the process of your application. The framework does (for the most part) not provide an error level as all exceptions are basically errors. If an exception is thrown, this always means that there is an error that the application cannot continue with.
If you want to discern between the exception types and write some as informational messages or warnings to your log, you'd have to inspect the exceptions in your error handler, e.g. by code similar to this:
public class MyErrorHandler : IErrorHandler
{
// ...
private static readonly Dictionary<Type, TraceLevel> _exceptionTraceLevelMappings;
static MyErrorHandler()
{
_exceptionTraceLevelMappings = new Dictionary<Type, TraceLevel>();
_exceptionTraceLevelMappings.Add(typeof(ApplicationException), TraceLevel.Information);
_exceptionTraceLevelMappings.Add(typeof(ArgumentException), TraceLevel.Warning);
}
private static TraceLevel GetLevelByExceptionType(Type exType)
{
// You might want to add a more sophisticated approach here (e.g. for base classes)
if (_exceptionTraceLevelMappings.ContainsKey(exType))
return _exceptionTraceLevelMappings[exType];
return TraceLevel.Error;
}
// ...
}
Based upon the comments, you want to discern between errors that are raised to coding mistakes and input data validation errors. In this case, you'd need to implement a CustomException type and use TryParse to validate input data:
public class MyValidationException : Exception
{
public MyValidationException(string message)
: base(message)
{
}
// A custom exceptions needs several constructors, so add them also
}
In your service code, you'd use TryParse as in your sample:
if(!long.TryParse("534543534", out value))
{
throw new MyValidationException("Input is Not Valid!!!");
}
In the mapping dictionary, you can register your exception type and assign TraceLevel.Information:
// ...
_exceptionTraceLevelMappings.Add(typeof(MyValidationException), TraceLevel.Information);
// ...
How can I write a catch all exception handler in a Class Library project in C#, which will give the outside caller only one Custom Exception on any exception occurring in the library.
Most nearest solution I found is to implement a Facade class, call low level classes from it, and write try..catch in every call from Facade which will throw single custom exception if any exception occurs underneath.
I searched for solutions, but got it only for Web Applications (using Application context for catching exceptions)
e.g. How to implement one "catch'em all" exception handler with resume?
I need to implement it at Class Library level or at consumer of library level, but good if that can be done by write minimum exception handling statements.
You could use:
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
{
var exception = e.ExceptionObject as Exception;
if (exception != null && exception.Source == "MyLib")
{
// Do stuff here
}
};
But seriously, don't do it. Exceptions shouldn't be handled this way, you should catch them locally.
You could use AppDomain.UnhandledException but make sure you read the documentation thoroughly - there are some exceptions that you can't handle, and it also depends on version of the framework that you are using.
I've got some UI code that looks like this:
try
{
SomeClass classInstance = new SomeClass(someId);
}
catch (Exception exception)
{
// Content wasn't created, show a message, stop processing
return;
}
It seems the try catch was added because the constructor for SomeClass would bomb out if the someId it receives isn't valid, and data couldn't be found in a DB.
Running this code through FXCop recently, it warns against using the general Exception, but all SomeClass does is throw a new Exception with a message to say it failed to initialize.
I guess the problem is that the class constructor should have it's own custom exception, which I could then handle in my UI, but I wonder what else I could do to the code above to handle the exception, that meets FXCop requirements?
FxCop's rule exists because the catch (Exception) block above catches all possible exceptions, including low-level exceptions like StackOverflowException that you probably can't catch in a useful way.
The right approach is definitely to throw a more specific type: either one you've invented, or an existing .NET framework exception type that closely matches your situation. (When in doubt, I normally go for InvalidOperationException.)
Alternatively, you could check the exact exception type when catching it. This won't prevent the FxCop warning, but it should address the underlying problem:
catch (Exception exception)
{
if (exception.GetType() == typeof(Exception))
{
// Content wasn't created, show a message, stop processing
return;
}
else
{
// Some other exception type that wasn't thrown from our code -
// delegate to a higher-level exception handler
throw;
}
}
You don't need a custom exception; just use one of the dozens that already exist in the framework for given circumstances. If someId is bad, throw an ArgumentException -- that's what it's made for. If something's null that shouldn't be, a NullReferenceException will occur; just let it be thrown. Etc. Throwing a plain Exception is a bit like saying "something went wrong -- read the message for details" rather than "this went wrong".
FxCop is complaining about catch (Exception) because it's too commonly abused to swallow up all exceptions rather than letting them propagate and be handled by code that knows how to do so. You should be able to say what types of exceptions are being thrown and catch those, while letting those you don't recognize make their way up the call stack.
You should fix the class constructor. Throwing Exception is never a good idea.
However, to work around the issue you have temporarily (as this is a horrible, unreliable hack), you could check the message of the exception against the one you're expecting:
catch (Exception exception)
{
if (exception.Message == "whatever your class sets the message to")
// Content wasn't created, show a message, stop processing
return;
else
// Any other exception should bubble
throw;
}
Using InvalidOperationException in place of throwing Exception sounds like it might be sensible.
If FXCop doesn't like handling the general Exception (and I tend to agree) then maybe you have access to SomeClass's source code. Modify the constructor to throw an exception that is more specific, e.g. ArgumentOutOfRangeException or some custom exception.
In that case your code would then look as follows:
try
{
SomeClass classInstance = new SomeClass(someId);
}
catch(ArgumentOutOfRangeException exception)
{
// Content wasn't created, show a message, stop processing
return;
}
As many others have said, the constructor should not be throwing a naked Exception. Seeing that the constructor retrieves data from DB and throws based on the result, the best solution is to create your own exception class.
Creating exceptions is super-easy in Visual studio. Just type in Exception and press TAB. It will then create the exception class with required constructors(all four of them). Do not be afraid to create classes that don't do very much, that's what they are designed for.
This is how I would write this class:
public class SomeClass {
public SomeClass(int someId) {
if (someId < 0) //validation on the ID, can it be negative?
throw new ArgumentException("someId", "ID cannot be negative");
//Perform DB operation
if (/*DB error - not found*/)
throw new DataNotFoundException("Cannot find record with ID " + someId);
}
}
[Serializable]
public class DataNotFoundException : Exception {
public DataNotFoundException() { }
public DataNotFoundException(string message) : base(message) { }
public DataNotFoundException(string message, Exception inner) : base(message, inner) { }
protected DataNotFoundException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
}