Why can't I catch this exception from a constructor? - c#

In this test code, why does the test fail with an ArgumentNullException, despite that it is handled?
[Test]
public void ExceptionBehaviorTest()
{
// This works. An instance is returned
var testInstance = (TestClass)Activator.CreateInstance(typeof(TestClass), "Hello World");
Assert.NotNull(testInstance);
// This passes. Exception is generated and caught
Assert.Throws<ArgumentNullException>(() => new TestClass(null));
try
{
// This throws ArgumentNullException but the catch handler is not invoked. This fails the test
testInstance = (TestClass)Activator.CreateInstance(typeof(TestClass), (string)null);
Assert.Fail("Should not get here");
}
catch (ArgumentNullException)
{
}
}
private sealed class TestClass
{
public TestClass(string arg)
{
Argument = arg ?? throw new ArgumentNullException(nameof(arg));
}
public string Argument
{
get;
}
}
If I run the code in the debugger, it stops in the TestClass ctor, saying that the exception is not handled. But the calling function is visible in the stack, so the problem is not related to some part being executed on a different thread.
[Background: In my real-world code, I'm iterating over a bunch of classes and testing whether they have a ctor with a specific argument. This is to prevent runtime errors later, as the classes are constructed using dependency injection.]

This is in the documentation
TargetInvocationException
The constructor being called throws an
exception.
So you need to catch TargetInvocationException in this situation, also if you like you can use when though I am not sure it helps with your test much
catch (TargetInvocationException ex) when (ex.InnerException is ArgumentNullException)
{
Console.WriteLine("Caught");
}

Related

C# Selected Overload Method On Runtime

namespace Rextester
{
public class BaseException : Exception
{
public BaseException() { }
}
public class Program
{
public static void MethodA(BaseException e)
{
Console.WriteLine("BaseException");
}
public static void MethodA(Exception e)
{
Console.WriteLine("Exception");
}
public static void Main(string[] args)
{
try
{
throw new BaseException();
}
catch (Exception e)
{
Console.WriteLine(e.GetType());
MethodA(e);
}
}
}
}
Hello guys i have one question according to the results of the above executed code :
e.GetType() == Rextester.BaseException
MethodA writes to console : Exception
So even though the Type of the exception is the derived class why in the run time is not called the specific overloaded method that has as parameter the BaseException and is called the one with Exception ?
At the following try/catch block:
try
{
throw new BaseException();
}
catch (Exception e)
{
Console.WriteLine(e.GetType());
MethodA(e);
}
an exception is thrown and at the catch the type of the exception is Exception, not BaseException. You basically, throw and a BaseException, but BaseException inherits Exception. So you get into the catch block.
If you wanted to catch the BaseException you should catch this first, since it's more specific.
try
{
throw new BaseException();
}
catch (BaseException e)
{
Console.WriteLine(e.GetType());
MethodA(e);
}
catch (Exception e)
{
Console.WriteLine(e.GetType());
MethodA(e);
}
By the way, it is more clear the name DerivedException than the name BaseException. All exception types in .NET as well as the custom exception types, those that we define for our needs inherit from the Exception class. So all of them are derived classes of the class Exception.
The above can also be found here as below:
Exceptions have the following properties:
Exceptions are types that all ultimately derive from System.Exception.
Once an exception occurs in the try block, the flow of control jumps to the first associated exception handler that is present
anywhere in the call stack. In C#, the catch keyword is used to define
an exception handler.
In addition to the above, you would find helpful the content of this, where it stated that
Multiple catch blocks with different exception filters can be chained together.
The catch blocks are evaluated from top to bottom in your code, but
only one catch block is executed for each exception that is thrown.
The first catch block that specifies the exact type or a base class of
the thrown exception is executed. If no catch block specifies a
matching exception filter, a catch block that does not have a filter
is selected, if one is present in the statement. It is important to
position catch blocks with the most specific (that is, the most
derived) exception types first.
Overloaded methods are bound at compile time.
At compile time, e has type Exception.
That's the reason.
It doesn't matter if the method is static or not. It's compile-time for both.
But after you catch the Exception you can do
dynamic dynEx = e;
MethodA(dynEx);
And you will get the right method called.
The function MethodA is declared as static. Hence any binding to function is at compile time.

how to pass types into test method

How can I pass types into my unit tests?
public void MethodUnderTest()
{
try
{
var businessService = _businessService.DoWork();
}
catch (SomeException exception)
{
//do some stuff
}
catch (SomeOtherException exception)
{
//do other stuff
}
}
My unit test should be something like this:
[TestCase(typeof(SomeException))]
[TestCase(typeof(SomeOtherException))]
public void UnitTest(Exception exception)
{
_businessService.Setup(x=>x.DoWork).Throws.InstanceOf<exception>();
//verify that when we called DoWork, that the logic inside of one of the catches was executed
}
One way this can be implemented would be, by utilizing inferred generics ..
you will have a test case source in your test fixture.
public static List< Exception > Exceptions => new List< Exception >
{
new InvalidOperationException(),
new OverflowException()
};
and then modify your unit test method as :
[Test]
[TestCaseSource(nameof( Exceptions ))]
public void UnitTest<T>( T exception ) where T : Exception, new(){
_businessService.Setup(x=>x.DoWork).Throws.InstanceOf<T>();
//verify that when we called DoWork, that the logic inside of one of the catches was executed
}
Then the code would infer the types from the instance of the exceptions in the test case source. I can't think of a way to do this with out instantiating the exceptions ...
You haven't said what you have tried that didn't work. On the surface, it appears easy enough, but perhaps I don't understand what you want to do.
The example unit test you show is incorrect. It takes an Exception as an argument, but you are giving it a Type. Based on your title, the test method should accept a type. Then do something like...
[TestCase(typeof(SomeException))]
[TestCase(typeof(SomeOtherException))]
public void UnitTest(Type exceptionType)
{
Assert.That(()=>_businessService.Setup(x=>x.DoWork),
Throws.InstanceOf(exceptionType));
}
```
Did I misunderstand the problem?

Handling exceptions when running nunit tests from console application

I'm trying to run nunit test cases from the console application using reflection. I get an exception which is not handled by my catch block. Could you give an advice how to handle all the exceptions from the invoked test methods?
static void Main(string[] args)
{
// Take all classes of the current assebly to which TestFixture attribute is applied
var testClasses = Assembly.GetExecutingAssembly().GetTypes().Where(c =>
{
var attributes = c.GetCustomAttributes(typeof(TestFixtureAttribute));
return attributes.Any();
});
foreach (var testClass in testClasses)
{
var testMethods = testClass.GetMethods().Where(m =>
{
var attributes = m.GetCustomAttributes(typeof (TestAttribute));
return attributes.Any();
});
var instance = Activator.CreateInstance(testClass);
foreach (var method in testMethods)
{
try
{
Action action = (Action) Delegate.CreateDelegate(typeof (Action),
instance, method);
action();
}
catch (AggregateException ae)
{
Console.WriteLine(ae.Message);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
It's really unclear why you're trying to do this, since there's already nunit-console that can run unit tests from a console application. It's also unclear what exception you don't think is being caught, but I suspect it's not the type you think it is. I took your code and put it into a fresh console application, along with some very basic tests:
[TestFixture]
public class SomeFailingTests
{
[Test]
public void Fails()
{
Assert.AreEqual(1, 0);
}
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestExceptionExpected()
{
}
[Test]
public void TestThrows()
{
throw new InvalidOperationException();
}
[Test]
[ExpectedException(typeof(InvalidOperationException))]
public void TestThrowsExpected()
{
throw new InvalidOperationException();
}
}
All of the tests that threw exceptions were caught by the line:
catch (Exception e)
This makes sense, since none of them threw an AggregateException. I suspect whichever test you are running is also not throwing one and is also being caught by your outer catch. A good start might be to rewrite this block as:
catch (Exception e)
{
Console.WriteLine(string.Format("{0}: {1}", e.GetType().Name, e.Message));
}
So that you can see any exception types that you aren't handling. At a very basic level, you may have to account for AssertionException for example.
If you want to support a similar feature set to other nunit runners you're also going to need to pay attention to the ExpectedException attribute on any methods you run and check to see if that exception is thrown when you invoke the method. You'll also need to check for the Ignored attribute...
As has been mentioned in my answer to this question, you may also need to pay attention to other test attributes such as TestCase and TestCaseSource if you want to capture all of the tests in the assembly.
Unless you're writing this as a learning exercise, you might want to reconsider your approach.

Return value to another class/object without added a relation between them C#

I having some classes related like the following domain drawing:
The Requestcontroller is running a loop in a ThreadPool, which on received messages will handle them and call some methods in FooClass, which then should throw exceptions if anything goes wrong.
In example (in some way pseudo-code):
class RequestController
{
private FooClass fooClass;
public RequestController(ref FooClass fooClass)
{
this.fooClass = fooClass;
}
void OnResponseReceived()
{
try
{
this.fooClass.ProcessingRequest("id", "requestType", 13);
}
catch(Exception ex)
{
Debug.Fail(ex.Message);
}
}
}
class FooClass
{
private object myObj;
[...]
public void ProcessingRequest(string id, string type, int count)
{
try
{
myObj.MethodAsync(id, type, RequestFailedCB, myObj);
//This method throws an Exception, that I want to be handled by RequestController class based on the Exception
}
catch(Exception)
{
throw;
}
}
}
So, my problem is that the Async method (MethodAsync in FooClass) will fail, and throw an Exception in FooClass, but it's giving me "Unhandle Exception". What I want is that the Requestcontroller is calling the method of FooClass, and if the async method that has been invoked in the FooClass.ProcessingRequest fails and throws an exception, which my RequestController should react on, and sending a message further on in the system, that there has been an error in the response received.
Would it be an idea to make the ProcessingRequest as and Callback method, or are there any better way to solve this purpose???
EDIT:
#KC-NH without posting pages of complex code, I'll try to get closer to the point.
As commented I forgot to mention that the project i .net 4 target. And the example posted in the FooClass method, is actually calling a .BeginTransfer of the UCMA 4 api, which I want to catch if it fails, and let the RequestController send a message about the failure further on in the system. The .BeginTransfer method returns IAsyncResult, and needs a Callback as one of the parameters.
The exception that the system throws, is inside this CB, but if I try to throw that exception from the Callback, I'm getting "Unhandled Exception", probably cuz the callback doesn't know where to throw that exception??
[.NET 4.5 specific solution]
You should always await async calls. await will rethrow exceptions as expected. This should correct your problem:
class RequestController
{
private FooClass fooClass;
public RequestController(ref FooClass fooClass)
{
this.fooClass = fooClass;
}
public async void OnResponseReceived()
{
try
{
await fooClass.ProcessingRequest();
}
catch (Exception ex)
{
System.Diagnostics.Debug.Fail(ex.Message);
}
}
}
public class FooClass
{
private object myObj;
public async Task ProcessingRequest()
{
await myObj.MethodAsync(id, type, RequestFailedCB, myObj);
}
}
I spoke with one of my colleagues today. He suggested that I used an EventHandler, to raise an event on exception catched in the callback method inside my FooClass. So the solution looks like this:
FooClass RequestFailedCB throws an exception
In RequestFailedCB the exception gets catched, and raising a ErrorEvent on my EventHandler.
The RequestController now gets information, that an event has been raised.
The RequestController will handle the error throw by the event, based on EventArgs and sender object, and can now send that error further on in the system.
Problem solved :) Thanks for all inputs.

How to expect an exception and still pass the test?

I have this:
Expect.Once.On( someObj ).Method( "SomeMethod" )
.With(1) // correct value is 2, I want this to fail
.Will( Throw.Exception( new Exception() ) );
An exception is thrown by nmock when it detects that I put 1 instead of 2. However, the test is failing (red) instead of passing. How to make this test pass, even though I'm expecting an exception?
If you're using NUnit then you can do:
Assert.Throws<Exception>(() => { someObj.SomeMethod(1); });
You can also decorate the test with an ExpectedException attribute, although that will cause the test to pass if any Exception is thrown, rather than just the statement you want to test.
EDIT: If you're using MSTest, as far as I know, you can only use attributes to expect exceptions i.e.
[ExpectedException(typeof(Exception)]
public void TestMethod() { ... }
You should consider throwing a more specific exception type from your mock and expecting that type instead of a plain Exception.
You could also define your own method to replicate the NUnit functionality:
public static class ExceptionAssert
{
public static void Throws<T>(Action act) where T : Exception
{
try
{
act();
}
catch (T ex)
{
return;
}
catch (Exception ex)
{
Assert.Fail(string.Format("Unexpected exception of type {0} thrown", ex.GetType().Name));
}
Assert.Fail(string.Format("Expected exception of type {0}", typeof(T).Name));
}
}
[ExpectedException (typeof(Exception))]
Edit: thanks, don't have the studio right now and was not 100% sure about the syntax.

Categories

Resources