PMF
PMF

Reputation: 17298

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

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.]

Upvotes: 0

Views: 219

Answers (1)

TheGeneral
TheGeneral

Reputation: 81583

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");
}

Upvotes: 2

Related Questions