{"record":{"id":"54eae86d5ed42c03","repo":"devlooped/moq","slug":"use-itexpr-isnull-tvalue-rather-than-a-null-argument-value","errorCode":null,"errorMessage":"Use ItExpr.IsNull<TValue> rather than a null argument value, as it prevents proper method lookup.","messagePattern":"Use ItExpr\\.IsNull<TValue> rather than a null argument value, as it prevents proper method lookup\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Moq/Protected/ProtectedMock.cs","lineNumber":459,"sourceCode":"                    Resources.UnexpectedPublicProperty,\n                    reflectedTypeName,\n                    property.Name));\n            }\n        }\n\n        static void ThrowIfVoidMethod(MethodInfo method)\n        {\n            if (method.ReturnType == typeof(void))\n            {\n                throw new ArgumentException(Resources.CantSetReturnValueForVoid);\n            }\n        }\n\n        static Type?[] ToArgTypes(object[] args)\n        {\n            if (args == null)\n            {\n                throw new ArgumentException(Resources.UseItExprIsNullRatherThanNullArgumentValue);\n            }\n\n            var types = new Type?[args.Length];\n            for (int index = 0; index < args.Length; index++)\n            {\n                if (args[index] == null)\n                {\n                    throw new ArgumentException(Resources.UseItExprIsNullRatherThanNullArgumentValue);\n                }\n\n                if (args[index] is not Expression expr)\n                {\n                    types[index] = args[index].GetType();\n                }\n                else if (expr.NodeType == ExpressionType.Call)\n                {\n                    types[index] = ((MethodCallExpression)expr).Method.ReturnType;\n                }","sourceCodeStart":441,"sourceCodeEnd":477,"githubUrl":"https://github.com/devlooped/moq/blob/89a5be629c752960fe403e95ff583e4ae6f00542/src/Moq/Protected/ProtectedMock.cs#L441-L477","documentation":"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.","triggerScenarios":"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.","commonSituations":"Building argument arrays dynamically where the array variable is null; misreading the Protected API and passing null instead of a placeholder expression array.","solutions":["Pass an explicit args array, using ItExpr.IsNull<T>() for each null argument, e.g. new object[] { ItExpr.IsNull<string>() }","If there are genuinely no arguments, omit the args parameter entirely instead of passing null"],"exampleFix":"// before\nmock.Protected().Setup<int>(\"Compute\", null);\n// after\nmock.Protected().Setup<int>(\"Compute\", ItExpr.IsNull<string>());","handlingStrategy":"validation","validationCode":"if (args == null) args = Array.Empty<object>(); // or build explicit ItExpr placeholders","typeGuard":"bool IsValidArgs(object[]? args) => args != null;","tryCatchPattern":"try { mock.Protected().Setup<int>(\"Compute\", args); } catch (ArgumentException) { /* rebuild args with ItExpr.IsNull */ }","preventionTips":["Never pass a null args array to Protected setups","Use ItExpr.IsNull<T>() for null arguments","Omit the args parameter entirely when there are no arguments"],"tags":["moq","mocking","null-argument","argument-exception"],"backgroundTag":"null-argument","analyzedSha":"89a5be629c752960fe403e95ff583e4ae6f00542","analyzedAt":"2026-09-16T05:31:39.496Z","contentChangedAt":"2026-09-16T05:31:39.496Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}