I have a parameterized unit test with decimal parameters.
[DataRow(0.0, 1.0, 1.0)]
[DataRow(1.0, 1.0, 2.0)]
[DataRow(2.0, 2.0, 4.0)]
[DataTestMethod]
public void TestAdd(decimal a, decimal b, decimal expectedAnswer)
{
var actualAnswer = a.Add(b);
Assert.AreEqual(expectedAnswer, actualAnswer);
}
Code language: C# (cs)
When I run the test, I get the following exception:
System.ArgumentException: Object of type ‘System.Double’ cannot be converted to type ‘System.Decimal’.
Solution
Change the parameters to doubles and convert them to decimals inside the test method.
[DataRow(0.0, 1.0, 1.0)]
[DataRow(1.0, 1.0, 2.0)]
[DataRow(2.0, 2.0, 4.0)]
[DataTestMethod]
public void TestAdd(double a, double b, double expectedAnswer)
{
decimal A = Convert.ToDecimal(a);
decimal B = Convert.ToDecimal(b);
decimal expected = Convert.ToDecimal(expectedAnswer);
var actualAnswer = A.Add(B);
Assert.AreEqual(expected, actualAnswer);
}
Code language: C# (cs)
Why is it throwing an exception?
You have to pass doubles, not decimals. DataRow() is an attribute, which has compiler-enforced parameter constraints. You get a compile-time error if you try to specify a decimal type, i.e. [DataRow(0.0m, 1.0m, 1.0m)].
The test framework runs your unit test using reflection. When a method is invoked using reflection, it has to try to match up the parameters you passed in with the method’s parameters.
Because you have to pass doubles, and the method has decimal parameter, it has to convert these doubles into decimals. Apparently when you are invoking a method using reflection, it can’t handle this conversion.
I can recreate this exception by using reflection to call a method, passing in a double where it expects a decimal:
double dbl = 1.0;
A A = new A();
A.GetType().GetMethod("DoNothing").Invoke(A, new object[] { dbl });
public class A
{
public void DoNothing(decimal a)
{
}
}
Code language: C# (cs)
According to the stack trace, the exception is coming from RuntimeType.TryChangeType(…). For some reason it can’t handle this conversion.