unit testing for ArgumentNullException by param name
Solution 1
You could explicitly catch the exception in your test and then assert the value of the ParamName
property:
try
{
//test action
}
catch(ArgumentException ex)
{
Assert.AreEqual(expectedParameterName, ex.ParamName);
}
Solution 2
Lee's answer is great, but the test will only fail if an ArgumentException is thrown with the wrong parameter name. If no exception is thrown, the test will pass. To remedy this, I added a bool in my test like this
// Arrange
var expectedParamName = "param";
bool exceptionThrown = false;
// Act
try
{
new Sut(null);
}
// Assert
catch (ArgumentNullException ex)
{
exceptionThrown = true;
Assert.AreEqual(expectedParamName, ex.ParamName);
}
Assert.That(exceptionThrown);
Solution 3
See this: http://msdn.microsoft.com/en-us/library/ms243315.aspx You can provide the expected message too:
[TestMethod]
[ExpectedException(typeof(ArgumentNullException), "routeCategoryServices")]
Requires two test cases though.
Simon
Updated on June 04, 2022Comments
-
Simon almost 2 years
I have a unit test and am checking for null exceptions of my controller constructor for a few different services.
[TestMethod] [ExpectedException(typeof(ArgumentNullException))]
In my controller constructor I have:
if (routeCategoryServices == null) throw new ArgumentNullException("routeCategoryServices"); if (routeProfileDataService == null) throw new ArgumentNullException("routeProfileDataService");
I have a unit test for each, but how can I distinguish between the two. I can leave the test as is as either of the checks could be throwing null so I want to test the exception by param name.
Is this possible?
-
Lee over 10 years@Simon - Personally I'd look at creating a method similar to NUnit's
Assert.Throws
method instead of using test attributes since the assertion is more local. Asserting on the message is potentially fragile and I would avoid it if possible. -
Paolo Tedesco over 10 years@Simon, you should go for this solution, in particular checking the ParamName rather than relying on the exception message is a very good approach.
-
Paolo Tedesco over 10 yearsActually, that parameter is rather misleading: it's not the expected message, but a message to print in case of errors (I had suggested the same, then deleted my answer after testing it and seeing it does not work).
-
Samuel over 10 years@PaoloTedesco thanks for the hint. I know that the Nunit's ExpectedException behaves the way I described but wasn't aware that mstest differs there.
-
Paolo Tedesco over 10 yearsI, too, was assuming that the MS attribute behaves like NUnit (which is more logical, I think).
-
MarkyDD over 7 yearsInstead you could just call
Assert.Fail();
after the statement that should throw the exception. -
LordWilmore over 6 yearsAdding to @MarkyDD's suggestion, suggest also adding a general catch statement after the one specific to the 'ArgumentNullException' catch section, and just call 'Assert.Fail()' in there. That way if any other type of exception is thrown then the test will fail.
-
Chris over 3 yearsWhile this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.