Как проверить с decimal.MaxValue?
Рассмотрим следующий тест:
public void FooTest(decimal? val)
{
Check.That(true).IsTrue();
}
Я хочу запустить этот тест с экстремальными значениями (т.е. MaxValue
и MinValue
).
[TestCase(decimal.MaxValue)]
Это приводит к следующей ошибке: Аргумент атрибута должен быть константным выражением, выражением типаof или выражением создания массива типа параметра атрибута
[TestCase(79228162514264337593543935)]
Теперь я получаю это: интегральная константа слишком велика
Последняя отчаянная попытка:
[TestCase(79228162514264337593543935M)]
Очевидно, я получаю это из-за приведения: Аргумент атрибута должен быть константным выражением, выражением типаof или выражением создания массива типа параметра атрибута
Как написать unit test с decimal.MaxValue
в качестве параметра? Я мог написать конкретный тест для этого проблемного случая, но я хотел бы знать, есть ли способ написать TestCase
, как это.
Ответы
Ответ 1
Decimal.MaxValue не является константой, это поле static
readonly
. Это означает, что вы не можете использовать его в атрибутах, поскольку атрибуты требуют констант. Вам придется жестко закодировать его.
Visual studio сделает вид const
, но на самом деле не.
bool isConstant = typeof (decimal)
.GetField("MaxValue", BindingFlags.Static | BindingFlags.Public)
.IsLiteral;
//isConstant will be false :(
Ответ 2
Теперь, когда все остальные сказали, почему эта проблема возникает, ваш код должен использовать атрибут TestCaseSource
для записи теста:
private static object[] TestValues =
{
new object[]{ Decimal.MaxValue },
new object[]{ Decimal.MinValue }
};
[TestCaseSource("TestValues")]
public void FooTest(decimal value)
{
Assert.That(value, Is.EqualTo(Decimal.MaxValue));
}
Ответ 3
Не имеет значения, пытаетесь ли вы использовать [TestCase(Decimal.MaxValue)]
или используйте литерал как [TestCase(1m)]
. Ни один из них не будет работать.
В соответствии со спецификацией С# (17.1.3, Типы параметров атрибутов):
Типы позиционных и именованных параметров для класса атрибута ограничены типами параметров атрибутов, которые:
• Один из следующих типов: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.
• Тип объекта.
• Тип System.Type.
• Тип перечисления, если он имеет общедоступную доступность, и типы, в которых он вложен (если есть), также имеют общедоступную доступность (§17.2).
• Одномерные массивы вышеуказанных типов.
Обратите внимание на отсутствие десятичного числа в элементе первого списка.
Сообщение об ошибке немного вводит в заблуждение, поскольку в той же спецификации также указывается, что decimal
может быть константным выражением (7.19).
Но если вы посмотрите код IL при создании decimal
, вы увидите, что он вызывает вызов конструктора: newobj System.Decimal..ctor
. И это в отличие от других литералов, например. ldc.r8 33 33 33 33 33 33 F3 3F
для var a = 1.2;
.