Как в MSTest проверить, что метод выбрасывает исключение?
Использование Assert.ThrowsException в MSTest
Начиная с MSTest v2 (который сейчас является стандартным), для проверки исключений существует удобный статический метод Assert.ThrowsException<T>. Он позволяет лаконично и читаемо проверить, что код выбрасывает ожидаемое исключение. Более того, этот метод возвращает сам объект исключения, что позволяет дополнительно проверить его свойства (например, сообщение).
Вот как будет выглядеть ваш тест для метода Divide:
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class MathTests
{
[TestMethod]
public void Divide_DivideByZero_ThrowsDivideByZeroException()
{
// Arrange
var calculator = new Calculator(); // предполагаем, что Divide - это метод класса Calculator
// Act & Assert
// Assert.ThrowsException вернет исключение, если оно было выброшено,
// или провалит тест, если исключения не было или оно другого типа.
var ex = Assert.ThrowsException<DivideByZeroException>(() => calculator.Divide(10, 0));
// Дополнительно можно проверить сообщение исключения
Assert.AreEqual("Делить на ноль нельзя!", ex.Message);
}
}
Как это работает?
- Лямбда-выражение:
() => calculator.Divide(10, 0)– это делегатAction, который содержит код, который, как ожидается, выбросит исключение. - Проверка типа: Если код в лямбде выбрасывает исключение типа
DivideByZeroException(или производного от него), тест проходит. Если исключение не выбрасывается или выбрасывается исключение другого типа (например,Exception), тест падает с понятным сообщением. - Возвращаемое значение: Метод возвращает перехваченное исключение, что позволяет проверить его свойства (
Message,InnerException,Dataи т.д.).
Что делать, если нужно проверить, что исключение НЕ выбрасывается?
Для этого не нужен специальный Assert. Просто вызовите метод без обертки в ThrowsException. Если исключение будет выброшено, тест сам упадет:
[TestMethod]
public void Divide_ValidInput_ReturnsResult()
{
// Arrange
var calculator = new Calculator();
// Act
var result = calculator.Divide(10, 2);
// Assert
Assert.AreEqual(5, result);
// Если бы Divide выбросил исключение, тест бы не дошел до этой строки и упал бы.
}
Важные замечания для начинающих
- Убедитесь, что у вас MSTest v2. Если вы используете старый MSTest v1 (из .NET Framework), то
Assert.ThrowsExceptionможет отсутствовать. В этом случае обновите пакет NuGet:Microsoft.NET.Test.SdkиMSTest.TestAdapter/MSTest.TestFramework. - Не используйте [ExpectedException] – этот атрибут устарел и не рекомендуется, так как он не позволяет точно указать, в какой строке должно произойти исключение, и не дает проверить его свойства.
- Проверяйте точный тип исключения. Если ваш метод выбрасывает
ArgumentException, а вы проверяете наException, тест пройдет, но это плохая практика. Всегда проверяйте самый конкретный тип.
Использование Assert.ThrowsException делает тесты чистыми, выразительными и соответствующими современным стандартам юнит-тестирования в MSTest.
Альтернатива: ручная проверка через try-catch (для старых версий MSTest)
Если по каким-то причинам вы не можете использовать MSTest v2 (например, работаете с очень старым проектом), можно написать проверку вручную. Этот подход менее элегантен, но полностью работоспособен:
[TestMethod]
public void Divide_DivideByZero_ThrowsDivideByZeroException_Manual()
{
// Arrange
var calculator = new Calculator();
// Act
try
{
calculator.Divide(10, 0);
// Если мы дошли до этой строки, исключение не было выброшено
Assert.Fail("Ожидалось исключение DivideByZeroException, но его не было.");
}
catch (DivideByZeroException ex)
{
// Исключение перехвачено - тест пройден.
// Дополнительно можно проверить сообщение
Assert.AreEqual("Делить на ноль нельзя!", ex.Message);
}
catch (Exception)
{
// Если выброшено исключение другого типа - тест тоже падает
Assert.Fail("Выброшено исключение неверного типа.");
}
}
Недостатки этого подхода:
- Много шаблонного кода, который отвлекает от сути теста.
- Легко забыть вызвать
Assert.Failили неправильно обработать catch-блоки. - Метод
Assert.ThrowsExceptionделает то же самое, но короче и надежнее.
Поэтому рекомендуется по возможности обновить MSTest до v2 и использовать встроенный метод.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги
Как написать REST API на Go за 30 минут: пошаговое руководство