Модульное тестирование и проверка сообщений исключения
Есть модульный тест проверяющий что при определенных условиях будет брошен exception, таких exception'в теоретически может быть несколько, отличаются они значением свойства message. Появилась идея проверять значения message. Хорошая ли это идея? Не приведет ли в дальнейшем к каким нибудь непредсказуемым поворотам, оказывающим влияние на поддерживаемость тестов и т.д. Делают ли так вообще?
Пример тестируемого метода:
public void SomeTestMethod(string input)
{
if (string.IsNullOrEmpty(input))
{
throw new BadRequestException("не указано значение параметра input");
}
if (input.Contains("drop"))
{
throw new BadRequestException("параметр input содержит недопустимый аргумент");
}
}
Тест:
[Fact]
public void SomeTestMethod_EmptyInput_ThrowException()
{
// Act & Assert
var exception = Assert.Throws<BadRequestException>(() => Sut.SomeTestMethod(string.Empty));
Assert.Equal("не указано значение параметра input", exception.Message);
}
[Fact]
public void SomeTestMethod_EmptyInput_ThrowException()
{
// Act & Assert
var exception = Assert.Throws<BadRequestException>(() => Sut.SomeTestMethod("drop"));
Assert.Equal("параметр input содержит недопустимый аргумент", exception.Message);
}
Ответы (2 шт):
А какая разница исключение или нет? Собственно тестирование это проверка какого-то действия, функционала. Если результат действия это исключение, то почему не протестировать? Исключение это не ошибка, а задуманное действие смысл которого избежание бесконечных проверок и не пропуск следующего за ним блока кода во избежание проблем во время работы. Проверка наших задуманных действий это нормально. То что в будущем будут или нет проблемы, от того что вы тестирует исключения, это вовсе задача про принципы. Если их вы соблюдаете то теоретически у вас не должно быть проблем
Я не сторонник проверять exception.Message в тестах. Как минимум потому, что в некоторых стандартных исключениях, если явно не указывать message, значение свойства Message будет зависеть от Culture процесса, на которых запускается тест (для английской - будет сообщение на английском языке, для русской - на русском и т.д). Иногда прибегаю к такому подходу (проверка exception.Message), но все же стараюсь избегать его.
В приведенном вами коде я вижу одну логику - параметр input - невалидный, поэтому тест будет валиться с BadRequestException. С этой точки зрения тестирующий тест может выглядеть так:
[Theory]
[InlineData("")]
[InlineData("drop")]
public void SomeTestMethod_InvalidInput_ThrowsBadRequestException(string invalidInput)
{
// Act & Assert
var exception = Assert.Throws<BadRequestException>(() => Sut.SomeTestMethod(invalidInput));
}
Если же вам все же нужно четко разделить эти два кейса ("пустое значение" и "недопустимое значение"), то можно создать отдельныеexceptions для каждого кейса, и в тестах уже отлавливать два разных типа exception.