devlooped/moq · error · ArgumentException

Use ItExpr.IsNull rather than a null argument value, as it…

Error message

Use ItExpr.IsNull<TValue> rather than a null argument value, as it prevents proper method lookup.

What it means

ProtectedMock.ToArgTypes validates the argument array passed to protected-member setups and rejects a null args array outright. Null arguments must be expressed with ItExpr.IsNull<TValue> so Moq can still resolve which overload/shape of the protected method to match.

Solutions

  1. Pass an explicit args array, using ItExpr.IsNull<T>() for each null argument, e.g. new object[] { ItExpr.IsNull<string>() }
  2. If there are genuinely no arguments, omit the args parameter entirely instead of passing null

Example fix

// before
mock.Protected().Setup<int>("Compute", null);
// after
mock.Protected().Setup<int>("Compute", ItExpr.IsNull<string>());
Defensive patterns

Strategy: validation

Validate before calling

if (args == null) args = Array.Empty<object>(); // or build explicit ItExpr placeholders

Type guard

bool IsValidArgs(object[]? args) => args != null;

Try / catch

try { mock.Protected().Setup<int>("Compute", args); } catch (ArgumentException) { /* rebuild args with ItExpr.IsNull */ }

Prevention

When it happens

Trigger: Passing a null object[] to ItExpr/Setup argument helpers, e.g. mock.Protected().Setup("Method", null) or an ItExpr.Is/It.IsAny call site forwarding null instead of an args array.

Common situations: Building argument arrays dynamically where the array variable is null; misreading the Protected API and passing null instead of a placeholder expression array.

Related errors


AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16). Data as JSON: /api/errors/54eae86d5ed42c03. Report an issue: GitHub.

Appendix: source

Thrown at src/Moq/Protected/ProtectedMock.cs:459

                    Resources.UnexpectedPublicProperty,
                    reflectedTypeName,
                    property.Name));
            }
        }

        static void ThrowIfVoidMethod(MethodInfo method)
        {
            if (method.ReturnType == typeof(void))
            {
                throw new ArgumentException(Resources.CantSetReturnValueForVoid);
            }
        }

        static Type?[] ToArgTypes(object[] args)
        {
            if (args == null)
            {
                throw new ArgumentException(Resources.UseItExprIsNullRatherThanNullArgumentValue);
            }

            var types = new Type?[args.Length];
            for (int index = 0; index < args.Length; index++)
            {
                if (args[index] == null)
                {
                    throw new ArgumentException(Resources.UseItExprIsNullRatherThanNullArgumentValue);
                }

                if (args[index] is not Expression expr)
                {
                    types[index] = args[index].GetType();
                }
                else if (expr.NodeType == ExpressionType.Call)
                {
                    types[index] = ((MethodCallExpression)expr).Method.ReturnType;
                }

View on GitHub (pinned to 89a5be629c)