I have an exception being thrown by multiple tests that contain some useful information. By default the failed unit test log does not contain that information since it is a property of a custom exception.
I can do this:
try
{
// Run code that casts MyException
}
catch (MyException e)
{
// Extra logging for e.SomeProperty
throw;
}
But then I will have to do this for each and every test. Is there somewhere I can do this for all of the tests of a test class? Kind of like a middleware in Asp.Net.
Or some alternative way to handle exception before XUnit.
If MyException is a type you define, you may want to consider changing Exception.Message to be a concatenation of what the user puts in, and the useful information, since generally you want to make the Message be as helpful to you as possible.
public class MyException : Exception
{
public MyException(string message)
: base($"{message}: {SomeProperty}") { }
// other constructors...
public required object SomeProperty { get; init; }
}
If however you cannot or don't want to, you could also have a helper function for your tests that uses a callback within a try-catch and rethrow the exception with more appropriate information. Exceptions can wrap inside other exceptions which allows each exception to be shown.
static void Do(Action act)
{
try
{
act();
}
catch (MyException my)
{
throw new($"something something foobar: {my.SomeProperty}", my);
}
}
(Bare in mind some linters will tell you throwing a bare Exception is bad, but for tests it shouldn't matter.)
You can finally use it in your tests like so:
[Fact]
void Foo() => Do(() =>
{
// your function goes here!
// you can simply throw the exception to test out how it'll look like
throw new MyException("yay") { SomeProperty = "context value" };
});
Related
I have a C# application that can load other dlls with Activator.CreateInstance(type), that implement a given interface (plugins).
Now I want to catch all exceptions thrown from that new instance in it's own exception handler (because I cannot be sure that every exception is handled by the plugin properly) to present a message like:
Plugin [PluginName] caused the following error: [Exception.Message]
I can subscribe to the AppDomain.CurrentDomain.UnhandledException event, but this catches all exceptions and not only the ones caused by a certain plugin and I also can't see [that the|what] plugin caused the exception.
Is it possible to assign a exception handler to the created instance?
Thanks in advance,
Frank
I'm not sure I understand your exact scenario, but a solution could be creating a wrapper class around the plugin object that takes care of making sure all potential exceptions are handled correctly:
public interface IPluginObject
{
void Foo();
IBlah Bar();
...
}
public Wrapper<T>: IPluginObject where T: IPluginObject
{
private readonly T inner;
public Wrapper(IPlugin obj) { inner = obj; }
public void Foo()
{
try { inner.Foo() }
catch ....
finally ...
}
public IBlah Bar()
{
try { return inner.Bar(); }
catch ...
finally ...
}
}
Cumbersome? Yes, but you do get the benefit of knowing exactly what plugin is being troublesome.
i want to use AOP to handle my error exception in Console application. ( it is not MVC i used attribute vase programing to handle errors in mvc but this is console app) My code below: ( if error occurs ,it should throw an error yo my attribute side code )
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class HandleError : Attribute
{
public HandleError(string description)
{
try
{
this.Description = description;
}
catch (Exception)
{
throw;
}
}
public string Description { get; set; }
}
this will call from my method :
[HandleError("Error occurs here")]
public static void MyMethod(string data)
{
throw new Exception();
Actually; i want to use AOP to handle exceptions inside my method. i have to call attributes if it error occurs. But How? ( please don't offer postsharp, it needs money. but i am open for opensource also)By the way; why it is not easy ,i don't understand.
Basically, what PostSharp does is to weave code into your assembly at compile time that is run before and after the methods that are marked with the attributes. This is very good from a performance point of view because there is no use of code that is created dynamically at runtime.
Some other AOP frameworks (or IoC containers) offer the option to generate dynamic proxies that contain code that intercepts the calls to the methods at runtime.
Either you use one of those frameworks (look for IoC and interception) or you implement a comparable functionality by yourself. Basically what you have to do is to move the code you want to intercept into a class and mark the methods as virtual. At runtime, you decorate the instance of the class with a dynamically created class that inherits from your class and overrides the methods so that the additional code is run before and after the call to the method.
However, there might be a simpler approach that fits the needs of a console application. Instead of marking the methods with an attribute, you could also create some helper functions that contain the code that you want to run before and after the method:
void Main()
{
int value = GetValue(123);
DoSomething(value);
}
void DoSomething(int myParam)
{
RunAndLogError(() => {
// Place code here
Console.WriteLine(myParam);
});
}
int GetValue(int myParam)
{
return RunAndLogError(() => {
// Place code here
return myParam * 2;});
}
void RunAndLogError(Action act)
{
try
{
act();
}
catch(Exception ex)
{
// Log error
throw;
}
}
T RunAndLogError<T>(Func<T> fct)
{
try
{
return fct();
}
catch(Exception ex)
{
// Log error
throw;
}
}
As you can see, there are two overloads of RunAndLogError, one for void methods, the other one for methods that return a value.
Another option is to use a global exception handler for this purpose; see this answer for details: .NET Global exception handler in console application
I use NUnit 3.0 to run tests.
My issue is the next: I have class with tests and in the constructor of this class there is a method that is run before all the tests (because it is in the constructor). While this method is executing there is an error occurs and then I handle it with CleanUp method. In the CleanUp method I use TestContext.CurrentContext.Result.Outcome.Status property to look at the status of the test I run.
The thing is that the test was not run at all (as pre-condition method was failed). So why this property tells me that the test was passed?
Here is a piece of my code:
public class DepositSuccessTests
{
//attributes
public DepositSuccessTests(string device, WayToPay merchant)
{
SetUp();
try
{
Deposit_Money(merchant); // this method invokes an exception
}
catch (Exception e)
{
CleanUp();
}
}
[Test]
//Test that I run but that is not executed because of exception in the constructor
public void Check_Transaction_Merchant_In_Transactions()
{
_orderVerifications.CheckTransactionMerchantInTransactions_Back(_merchant);
}
[TearDown]
public void CleanUp()
{
//In the next line my test result is "Passed"
if (TestContext.CurrentContext.Result.Outcome.Status == TestStatus.Failed)
{
//Do something
}
_driver.Dispose();
}
}
Even tho the line Deposit_Money(merchant); has caused an exception you have caught it, so as far as the runner is concerned there is no problem, all code has gone through with no errors. You know there was a problem, I know there was a problem but the runner doesn't.
If you explicitly fail in the catch, then it will mark it as non-passing.
try
{
Deposit_Money(merchant); // this method invokes an exception
}
catch (Exception e)
{
Assert.Fail(); /// Explicitly fail the test
CleanUp();
}
You need to allow the exception to be thrown in the test, as strictly speaking, your test has indeed passed.
Remove the error checking in your test, allow the exception to be thrown, and you should see the test result as failed.
I want to overload the throw keyword to catch a class which inherits from Exception and to have it do some logging and other stuff before the actual throw. Is this possible? Or do I have to use a regular function?
I've tried:
public class cSilException : Exception
{
private string m_strMsg;
public override void throw(cSilException ex)
{
}
...
...
}
Register the event AppDomain.FirstChanceException. There you get all exceptions before the are actually thrown. In the event handler you can check for your exception and do the required logging.
No magic and no bad design.
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;
DoBadThings();
}
private static void DoBadThings()
{
DoOneLevelBelow();
}
private static void DoOneLevelBelow()
{
for(int i=0;i<10;i++)
{
try
{
if (i == 5)
{
var invalidCast = (string)((object)i);
}
else
{
throw new InvalidTimeZoneException();
}
}
catch
{
}
}
}
static void CurrentDomain_FirstChanceException(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs e)
{
if( e.Exception is InvalidCastException)
{
LogInvalidCast((InvalidCastException)e.Exception);
}
}
private static void LogInvalidCast(InvalidCastException invalidCastException)
{
Console.WriteLine("Got Invalid cast: {0}", invalidCastException);
}
This will lead to:
Got invalid cast: System.InvalidCastException: The object of the type
"System.Int32" cannot be converted to "System.String". at
ThrowTest.Program.DoOneLevelBelow() in
d:\Media\Blog\ThrowTest\Program.cs:line 31.
Please note since you are getting the exception before the stack is unwound you will see only the method where it did happen but not the calling methods since the stack was not unwound yet.
If you want the complete call stack you can use Environment.StackTrace to get all stack frames.
What you want to do is add a constructor to your exception and do whatever you need to do within that constructor.
public class cSilException : Exception
{
//constructor
public cSilException()
{
// do stuff here
}
}
Your notion of "overloading the throw keyword" was quite, er, how to put it, psychedelic.
Of course, as many have pointed out, it is best to avoid doing this if your intention is to do things such as logging. Alois Kraus has posted another answer with a very good suggestion.
I wouldn't recommend logging anything inside the exception's constructor since it violates the single responsibility principle and is considered a bad design. Also, the fact that an exception was created doesn't necessarily mean it has been thrown, and besides, exceptions can be caught and rethrown - these things may lead to incorrect logging messages.
Instead, you can use an application-wide exception handler which will handle exceptions according to your predefined policy. For example, you can have a look at the Enterprise Library Exception Handling Block and specifically this section.
You can't overload throw it is an integral part of the language (not a member of a class)
If you want to handle a specific Exception you should catch that exception:
try
{
// your code, which throws some exceptions
}
catch(cSilException csEx)
{
// handle csEx
throw; // rethrow this exception
}
catch(Exception ex)
{
// handle all other exceptions
}
This code catches the special exception cSilExceptionin a different code block than all other exceptions.
Look for methods and members of Exception class. You can define constructor for cSilException like this
public cSilException(string message)
{
Message = message;
}
and than in catch (cSilException ex) do Console.WriteLine(ex.Message);
I have built an app in C#, where I have to break just after an exception is caught. I used return, but it returned to the module which called this module and continued execution. What should be done?
My code looks likes this:
class a
{
b bee=new b{};
bee.read(name);
bee.write(name);// don want this to get executed if exception is thrown
}
class b
{
read(string name)
{
try{}
catch
{
//caught;
//what should be put here so that it just stops after dialog
// box is shown without moving to the write method?
}
write(string name) {}
}
}
Your code sample is incorrect, but let's assume that you have a method with this code inside:
void M()
{
b bee=new b();
bee.read(name);
bee.write(name);// don want this to get executed if exception is thrown
}
If so, you have to catch exceptions in this method, not in read method. Like so:
void M()
{
try {
b bee=new b();
bee.read(name);
bee.write(name);// don want this to get executed if exception is thrown
}
catch(Exception e) {
// Proper error handling
}
}
In read method you should not suppress exceptions. Either don't catch them at all or rethrow them (or better yet, throw a new exception with the old one being its InnerExeption).
If you handle exceptions in method M this way, he line bee.write(name) won't be executed if an exception occurs somewhere inside bee.read(name).
Let the exception bubble up to the calling method:
class A {
public void Method() {
B bee = new B{};
try {
bee.Read(name);
bee.Write(name);
} catch(Exception ex) {
// handle exception if needed
}
}
}
class B {
public void Read(string name) {
try{
...
} catch(Exception ex) {
// handle exception if needed
throw;
}
}
public void Write(string name) {
}
}
Note: You should catch a more specific exception class if posible, instead of catching the base class Exception. The catch syntax without an excpetion parameter is obsolete.
you can do this as follows
class a
{
b bee = new b();
try
{
bee.read(name);
bee.write(name);
}
catch(Exception ex)
{
//handle error here
}
}
class b
{
//These are your method implementations without catching the exceptions in b
read
write
}
If you catch the exception in the method then you won't have any way of knowing the exceution state of the method without hangind some kind of error status off the method. Whether that is a boolean return or an error code that is accesible in b.
Why not have the read method return a value that means something to the caller? so the caller inspects the return from read and if it's (for example) null it doesn't call write. Alternatively your read method could return an enum value that tells the caller the condition with which the read method exited.
As another option your caller could implement an interface with a doNotProceed method, then pass itself to the read method. On exception read calls caller.doNotProceed, setting an internal variable within the caller object and this tells it to not proceed to write.
You have plenty of options
You can use return statement or re throw the error and put another a parent try catch , but its better you restructure your code.