Jetnor
Jetnor

Reputation: 531

Issue with Assert.Throws Exception in NUnit testing

I am trying out NUnit, Unit Testing and Integration testing for the first time. I have been reading up and doing lots of online courses. As I'm sure you know very well it's something knowing theory and doing it in practice.

I am stuck on a particular test. The application that I have is in C# .Net 3.5.

I am trying to assert that a method with a certain bad input will throw a particular exception. When I run the method with the same input given to the test the expected exception is thrown.

The method being tested code is:

 private static bool FilePathHasInvalidChars(string userInputPath)
{
    try
    {
        Path.GetFullPath(userInputPath);//this is where the warning appears

    }
    catch (Exception e)
    {
        Log.Error(String.Format(
            "The Program failed to run due to invalid characters or empty string value for the Input Directory. Full Path : <{0}>. Error Message : {1}.",
            userInputPath, e.Message), e);
        return true;

    }
    return false;
}

I want to check that the above code can catch an exception if the provided input directory is not meeting the criteria.

The Unit test that I have at the moment is:

    [Test]
    public void can_throws_exception_for_empty_string()
    {
        var testDirectory = "";
        var sut = new DirectoryInfoValidator();

        Assert.Throws<ArgumentNullException>(() => sut.FilePathHasInvalidChars(testDirectory));
    }

The problem I have is that the test allways fails and if I check the return it states that It expected an ArgumentNull exception but was null. I have taken a screenshot of the output from the test: Asstert.Throws test output

Any idea what I might be doing wrong? EDIT: By the way I have also attempted to use

[ExpectedException(typeof(ArgumentNullException), ExceptionMessage= "Log Message", MatchType=MessageMatch.Contains)]

Have had same result with that.

On an ending note I am not sure if this is considered an Integration test or a Unit test given that my method uses Path.GetFullPath(string directory). Anyway my main issue right now is understanding what I am doing wrong. :)
Many thanks, Jetnor.

UPDATE: After taking all the points into consideration and looking at my system's needs I have decided not to throw an exception. Instead I have decided to create tests which cover the different possible exceptions that can occur in my situation. The test method looks like this:

        [Test]
    public void returns_true_for_empty_string()
    {
        var testDirectory = "";
        var sut = new DirectoryInfoValidator();
        var isInvalidPath = sut.FilePathHasInvalidChars(testDirectory);
        Assert.That(isInvalidPath, Is.True);
    }

This is a starting point. I inted to use the [TestCase] option by providing all the inputs to one test and checking all of them at the same time. Thanks for your help guys.

Upvotes: 1

Views: 6207

Answers (2)

Mark Shapiro
Mark Shapiro

Reputation: 1232

Your method FilePathHasInvalidChars does not throw an exception. An exception is thrown inside of your method, but your method catches and handles the exception. Your method will always return a valid value.

If you want your method to throw an ArgumentNullException rather than logging and swallowing it, try this:

private static bool FilePathHasInvalidChars(string userInputPath)
{
    try
    {
        Path.GetFullPath(userInputPath);//this is where the warning appears

    }
    catch (ArgumentNullException) {
        Log.Error("The Program failed to run due to a null string value for the Input Directory.");
        throw;
    }
    catch (Exception e)
    {
        Log.Error(String.Format(
            "The Program failed to run due to invalid characters or empty string value for the Input Directory. Full Path : <{0}>. Error Message : {1}.",
            userInputPath, e.Message), e);
        return true;

    }
    return false;
}

With this modification, if userInputPath is null your method will log and re-throw the ArgumentNullException, and your unit test will see the exception and pass.

Upvotes: 6

AllenG
AllenG

Reputation: 8190

Your code does not throw an ArgumentNullException. Based on your code, it should never* throw any exception- it should simply return true or false.

Change your test to the NUnit equivalent of:

Assert.IsTrue(() => sut.FilePathHasInvalidChars(testDirectory));

Or, if an empty string SHOULD throw an ArgumentNullException, modify the code to something like the following**:

private static bool FilePathHasInvalidChars(string userInputPath)
{
    if(string.IsNullOrWhiteSpace(userInputPath) throw new
        ArgumentNullException("userInputPath");
    try
    {
        Path.GetFullPath(userInputPath);//this is where the warning appears

    }
    catch (ArgumentException e)
    {
        Log.Error(String.Format(
            "The Program failed to run due to invalid characters or empty string value for the Input Directory. Full Path : <{0}>. Error Message : {1}.",
            userInputPath, e.Message), e);
        throw;    
    }
    catch (Exception e)
    {
        Log.Error(String.Format(
            "The Program failed to run due to invalid characters or empty string value for the Input Directory. Full Path : <{0}>. Error Message : {1}.",
            userInputPath, e.Message), e);
        return true;

    }
    return false;
}

*- For a value of "never" that means "so rarely you're unlikely to have to consider it"

**- I haven't tried to compile that, so there may be errors; it's just a starting point.

Upvotes: 3

Related Questions