I'm not sure if I should ask this here but here we go, while unit testing a private static method that has as parameter a short I'm getting a MissingMethodException only when this parameter is 0.
I'm using VS 2010 SP1 targeting the Framework 4 (full), here is the bare minimum code to reproduce this error (we are upgrading a VB6 code so don't be rude):
[DataContract]
public enum NotificationResult
{
[EnumMember]
Success,
[EnumMember]
StoredError,
[EnumMember]
InvalidId,
[EnumMember]
OperationError,
}
public sealed class NotificationContext
{
private static NotificationResult GetExecuteResult(short result)
{
NotificationResult executeResult;
switch (result)
{
case 0:
executeResult = NotificationResult.Success;
break;
case 1:
executeResult = NotificationResult.StoredError;
break;
case 2:
executeResult = NotificationResult.InvalidId;
break;
default:
executeResult = NotificationResult.OperationError;
break;
}
return executeResult;
}
}
Here is how I'm testing the code:
PrivateType privateHelperType = new PrivateType(typeof(NotificationContext));
var actual = (NotificationResult)privateHelperType.InvokeStatic(
"GetExecuteResult", (short)1);
var actual2 = (NotificationResult)privateHelperType.InvokeStatic(
"GetExecuteResult", (short)0); //here is where i get the exception
In the first invocation i get the expected result, in the second invocation I get the exception (I added the cast to short thinking that maybe the exception was because it was not finding a method with an int as a parameter).
Is anybody able to reproduce the behavior?, am I doing something wrong?
Thanks for your help.
The problem is that there are two overloads of this method (there are others, but they don't matter here):
public Object InvokeStatic(string name, params Object[] args)
public Object InvokeStatic(string name, BindingFlags invokeAttr, params Object[] args)
The difference is that the second overload has a parameter of type BindingFlags
, which is an enum
. And when you pass literal 0
as the second parameter, this overload is chosen, because the literal 0
is implicitly convertible to any enum
and not using params
is deemed better than using it in overload resolution. So, basically
privateType.InvokeStatic("GetExecuteResult", 1)
is compiled into privateType.InvokeStatic("GetExecuteResult", new object[] { 1 })
privateType.InvokeStatic("GetExecuteResult", 0)
is compiled into privateType.InvokeStatic("GetExecuteResult", 0, new object[] { })
This is the cause of your problem. I think the cleanest way to avoid it would be to create the array explicitly:
privateType.InvokeStatic("GetExecuteResult", new object[] { 0 })
Except in your code you don't pass the literal 0
to the method, you cast it first. According to the specification, the BindingFlags
overload should not be chosen in this case. But errors like this are a known bug, that won't be fixed, because it would break some working programs.
Interesting... I was able to reproduce it, and I found a way to fix it.
short s = 0;
var actual2 = (NotificationResult)privateHelperType.InvokeStatic(
"GetExecuteResult", s);
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