Модульный тест MSTest, подтверждающий определенные сообщения об исключениях

Я пишу свой первый модульный тест для очень маленького проекта. Здесь ожидаемый результат и результат возвращают исключение ArgumentNullException, но тест все равно не проходит. Есть идеи, почему?

        [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--------

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

        }

Ошибка:

Ожидается: System.ArgumentNullException: значение не может быть нулевым.

Фактическое: System.ArgumentNullException: путь не может быть нулевым. Имя параметра: путь

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

person user2994921    schedule 28.04.2020    source источник
comment
Пожалуйста, также поделитесь, как выглядит метод InsertFileBeginning   -  person Pavel Anikhouski    schedule 28.04.2020
comment
Пожалуйста, посмотрите этот поток, это может быть полезно для вашего случая модульное тестирование для ArgumentNullException по имени параметра   -  person Pavel Anikhouski    schedule 28.04.2020
comment
@PavelAnikhouski большое спасибо, да, этот обходной путь сработал, сравнивая имя параметра.   -  person user2994921    schedule 28.04.2020


Ответы (2)


Посмотри на это;

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

ожидаемое исключение является объектом типа ArgumentNullException, а результат также является объектом типа ArgumentNullException, однако это не один и тот же объект! у вас есть 2 экземпляра одного типа.

Теперь AreEqual(..) использует .Equals из того, что я смог собрать в Интернете.

Я думаю, что вы сравниваете ссылки ожидаемого исключения с результатом здесь. Они, конечно, не одинаковы. Вместо этого вам следует (если мои предположения верны) проверить, относится ли результат к тому же типу, а не использовать AreEqual(..).

Кажется, вы можете использовать для этого этот метод: Assert.IsInstanceOfType https://docs.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));
person sommmen    schedule 28.04.2020
comment
Это была именно проблема. Спасибо. Теперь только я понимаю, что было не так в моей кодировке. Спасибо всем за ваше время и помощь. - person user2994921; 28.04.2020

Прежде всего, не используйте [ExpectedException]. Это оказалось плохой практикой, потому что исключение может возникнуть где угодно. И поскольку вы используете Assert.ThrowsException, который дальше не выбрасывает исключение, ваш тест все равно провалится.

Во-вторых, я не совсем в курсе MSTest, но кажется, что он терпит неудачу, если исключение не выдается с сообщением по умолчанию. Но если вы не можете указать ожидаемое сообщение об ошибке в Assert.ThrowsException, вы можете реализовать свой собственный метод assert:

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

Отказ от ответственности: я не знаю, есть ли в MSTest методы Assert.IsInstanceOf и т. д., но вы видите смысл.

person György Kőszeg    schedule 28.04.2020