This is a corner case that I only ran into in due to work on the analyzers in nunit/nunit.analyzers#54, and my guess is that very few will run into this problem. Nevertheless, I think we could improve the error message, and fix seems simple and safe.
Given a generic test method with no parameters we get a failure that is difficult to interpret for the users (see last example below for more detail). E.g. the test
[Test]
public void TestWithGenericTypeThatFailsWithUnusableMessage<T>()
{
}
fails with System.InvalidOperationException : Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.
I propose that we change the code at
|
if (testMethod.Method.IsGenericMethodDefinition && arglist != null) |
|
{ |
|
Type[] typeArguments; |
|
if (!new GenericMethodHelper(testMethod.Method.MethodInfo).TryGetTypeArguments(arglist, out typeArguments)) |
|
return MarkAsNotRunnable(testMethod, "Unable to determine type arguments for method"); |
|
|
|
testMethod.Method = testMethod.Method.MakeGenericMethod(typeArguments); |
|
parameters = testMethod.Method.GetParameters(); |
|
} |
so that we also return
MarkAsNotRunnable(testMethod, "Unable to determine type arguments for method") if
arglist == null instead of failing hard later on.
Context
The following test is executed without problem, as NUnit determines that int can be used as T.
[TestCase(1, ExpectedResult = 1)]
public T TestWithGenericTypeThatWorks<T>(T arg1)
{
return arg1;
}
But if we cannot determine the type of T using the parameters of the method
[TestCase(1, ExpectedResult = 1)]
public T TestWithGenericTypeThatFailsWithUsableMessage<T>(int arg1)
{
return default(T);
}
then we mark the test as not runnable with the message Unable to determine type arguments for method.
However, if the method does not have any parameters
[Test]
public void TestWithGenericTypeThatFailsWithUnusableMessage<T>()
{
}
then we fail with the message System.InvalidOperationException : Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true. and a stacktrace
at System.Reflection.RuntimeMethodInfo.ThrowNoInvokeException()
at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at NUnit.Framework.Internal.Reflect.InvokeMethod(MethodInfo method, Object fixture, Object[] args) in C:\src\nunit\nunit\src\NUnitFramework\framework\Internal\Reflect.cs:line 266
This is a corner case that I only ran into in due to work on the analyzers in nunit/nunit.analyzers#54, and my guess is that very few will run into this problem. Nevertheless, I think we could improve the error message, and fix seems simple and safe.
Given a generic test method with no parameters we get a failure that is difficult to interpret for the users (see last example below for more detail). E.g. the test
fails with
System.InvalidOperationException : Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.I propose that we change the code at
nunit/src/NUnitFramework/framework/Internal/Builders/NUnitTestCaseBuilder.cs
Lines 221 to 229 in db5bee0
MarkAsNotRunnable(testMethod, "Unable to determine type arguments for method")ifarglist == nullinstead of failing hard later on.Context
The following test is executed without problem, as NUnit determines that
intcan be used asT.But if we cannot determine the type of
Tusing the parameters of the methodthen we mark the test as not runnable with the message
Unable to determine type arguments for method.However, if the method does not have any parameters
then we fail with the message
System.InvalidOperationException : Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.and a stacktrace