Consider the following test:
public void FooTest(decimal? val)
{
Check.That(true).IsTrue();
}
I want to run this test with extreme values (i.e. MaxValue
and MinValue
).
[TestCase(decimal.MaxValue)]
This outputs the following error : An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
[TestCase(79228162514264337593543935)]
I get this one now : Integral constant is too large
One last desperate try:
[TestCase(79228162514264337593543935M)]
Obviously I get this one because of the cast : An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
How does one write a unit test with decimal.MaxValue
as a parameter? I could write a specific test for this problematic case but I would like to know if there's a way to write a TestCase
like this.
Now that all others have said, why this problem occurs, your code should use the TestCaseSource
attribute to write your test:
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));
}
Decimal.MaxValue is not a constant, it is a static
readonly
field. Which means you can't use it in attributes as attributes require constants. You'll have to hard code it.
Visual studio will pretend it as a const
but it is actually not.
bool isConstant = typeof (decimal)
.GetField("MaxValue", BindingFlags.Static | BindingFlags.Public)
.IsLiteral;
//isConstant will be false :(
It doesn't matter whether you try to use [TestCase(Decimal.MaxValue)]
or use a literal like [TestCase(1m)]
. Neither will work.
According to the C# specification (17.1.3, Attribute parameter types):
The types of positional and named parameters for an attribute class are limited to the attribute parameter types, which are:
• One of the following types: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.
• The type object.
• The type System.Type.
• An enum type, provided it has public accessibility and the types in which it is nested (if any) also have public accessibility (§17.2).
• Single-dimensional arrays of the above types.
Notice the absence of decimal in the first list item.
The error message is a bit misleading because same specification also says that a decimal
can be a constant expression (7.19).
But if you look at the IL code when creating a decimal
you'll see that it actually invokes a constructor call: newobj System.Decimal..ctor
. And that's unlike other literals, e.g. ldc.r8 33 33 33 33 33 33 F3 3F
for var a = 1.2;
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With