Skip to content

Better error message for generic test where type parameter cannot be determined #3215

Description

@mikkelbu

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions