2

I'm writing my first Unit test for very small project. Here the expected result and result both return a ArgumentNullException but the test still fails. Any idea why?

        [TestMethod]
        public void InsertFileBeginning_FilePathNull_ReturnArgumentNullException()
        {
            // Arrange
            var generateFile = new GenerateFile();
            string parameter = null; //pass FilePath Null

            var expectedExcetpion = new ArgumentNullException();

            // Act & Assert
            var result = Assert.ThrowsException<ArgumentNullException>(() => generateFile.InsertFileBeginning(parameter));
            Assert.AreEqual(expectedExcetpion, result);

        }

------InsertFileBeginning function--------

public void InsertFileBeginning(string filePath)
        {
            try
            {
                using (var fs = new FileStream(filePath, FileMode.Create))
                {
                    Byte[] metadata = new UTF8Encoding(true).GetBytes("THis is a test content");
                    fs.Write(metadata, 0, metadata.Length);

                }
            }
            catch (Exception exception)
            {
                throw exception;
            }

        }

Error:

Expected: System.ArgumentNullException: Value cannot be null.

Actual: System.ArgumentNullException: Path cannot be null. Parameter name: path

Message: Assert.AreEqual failed. Expected:<System.ArgumentNullException: Value cannot be null.>. Actual:<System.ArgumentNullException: Path cannot be null.
Parameter name: path
   at SmartTestSelecter.GenerateFile.InsertFileBeginning(String filePath) in C:\Users\CC\SmartTestSelecter\GenerateFile.cs:line 31
   at SmartTestSelecterUnitTests.GenerateFileTest.<>c__DisplayClass0_0.<InsertFileBeginning_FilePathNull_ReturnArgumentNullException>b__0() in C:\Users\CC\STSUnitTests\GenerateFileTest.cs:line 21
   at Microsoft.VisualStudio.TestTools.UnitTesting.Assert.ThrowsException[T](Action action, String message, Object[] parameters)>. 
user2994921
  • 89
  • 1
  • 14
  • Please, also share how does `InsertFileBeginning` method look like – Pavel Anikhouski Apr 28 '20 at 08:53
  • 1
    Please, have a look at this thread, it might be helpful for your case [unit testing for ArgumentNullException by param name](https://stackoverflow.com/questions/21379378/unit-testing-for-argumentnullexception-by-param-name) – Pavel Anikhouski Apr 28 '20 at 08:54
  • @PavelAnikhouski thank you very much yes this workaround did work comparing the parameter name. – user2994921 Apr 28 '20 at 09:07

2 Answers2

2

First of all, do not use [ExpectedException]. It turned out to be a bad practice because the exception can occur anywhere. And since you use Assert.ThrowsException, which does not throws the exception further, your test would fail anyway.

Secondly, I'm not quite up-to-date regarding MSTest but it seems it fails if the exception is not thrown with the default message. But if you can't specify the expected error message in Assert.ThrowsException, then you can implement your own assert method:

public static void Throws<T>(Action action, string expectedMessageContent = null)
    where T : Exception
{
    try
    {
        action.Invoke();
    }
    catch (Exception e)
    {
        Assert.IsInstanceOf(typeof(T), e);
        Assert.IsTrue(expectedMessageContent == null
            || e.Message.Contains(expectedMessageContent), $"Expected message: {expectedMessageContent}{Environment.NewLine}Actual message:{e.Message}");
        return;
    }

    Assert.Fail("No exception was thrown");
}

Disclaimer: I don't know whether MSTest has Assert.IsInstanceOf, etc methods but you see the point.

György Kőszeg
  • 17,093
  • 6
  • 37
  • 65
2

Look at this;

var expectedExcetpion = new ArgumentNullException();
// Act & Assert
var result = Assert.ThrowsException<ArgumentNullException>(() => generateFile.InsertFileBeginning(parameter));
Assert.AreEqual(expectedExcetpion, result);

expectedException is an Object of type ArgumentNullException and result is also an object of type ArgumentNullException - however they're not the same object! you have 2 instances of the same type.

Now AreEqual(..) uses .Equals from what i could gather online.

I think that you're comparing the references of expectedException with result here. They are of course not the same. What you should instead do (if my assumptions are right) is check if the result is of the same type, rather than use AreEqual(..).

It seems you can use this method for that: Assert.IsInstanceOfType https://learn.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.testtools.unittesting.assert.isinstanceoftype?view=mstest-net-1.2.0

e.g.:

Assert.IsInstanceOfType(result, typeof(ArgumentNullException));
sommmen
  • 6,570
  • 2
  • 30
  • 51
  • 1
    This was exactly the problem. Thank you. Now only I understand what was wrong in my coding. Thank you all for your time and help. – user2994921 Apr 28 '20 at 09:10