unit testing for ArgumentNullException by param name

11,494

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.

Share:
11,494
Simon
Author by

Simon

Updated on June 04, 2022

Comments

  • Simon
    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
    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
    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
    Paolo Tedesco over 10 years
    Actually, 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
    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
    Paolo Tedesco over 10 years
    I, too, was assuming that the MS attribute behaves like NUnit (which is more logical, I think).
  • MarkyDD
    MarkyDD over 7 years
    Instead you could just call Assert.Fail(); after the statement that should throw the exception.
  • LordWilmore
    LordWilmore over 6 years
    Adding 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
    Chris over 3 years
    While 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.