devlooped/moq · error · ArgumentException

No protected method . found whose signature is compatible…

Error message

No protected method {0}.{1} found whose signature is compatible with the provided arguments ({2}).

What it means

ProtectedMock's string-based Setup/Verify for methods throws ArgumentException with Resources.MethodMissing when reflection cannot find a protected method with the given name whose parameters are compatible with the supplied argument values/expressions. The message lists T's name, the method name, and the formatted argument types so the signature mismatch is visible.

Solutions

  1. Match the argument expressions to the protected method's exact parameter types (use ItExpr.IsAny<T>() with the right type)
  2. Check the protected method's signature and pick the correct overload
  3. Ensure the method is protected/non-public instance, not public (public triggers a different guidance path)
  4. Cast literals to the exact parameter type expected

Example fix

// before (T: protected int Compute(int x))
mock.Protected().Setup<int>("Compute", ItExpr.IsAny<long>());
// after
mock.Protected().Setup<int>("Compute", ItExpr.IsAny<int>());
Defensive patterns

Strategy: validation

Validate before calling

static bool HasProtectedMethodWithArgs(Type target, string name, params Type[] argTypes) =>
    target.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
          .Any(m => m.Name == name
                    && m.GetParameters().Select(p => p.ParameterType).SequenceEqual(argTypes));

Try / catch

try { mock.Protected().Setup<int>("Compute", ItExpr.IsAny<int>()); }
catch (ArgumentException ex) when (ex.Message.StartsWith("No protected method")) { /* fix name or argument types */ }

Prevention

When it happens

Trigger: mock.Protected().Setup<int>("Compute", ItExpr.IsAny<long>()) where T has a Compute(int) protected method — the name exists but argument types (or argument count) do not match any protected overload.

Common situations: Passing wrong argument types (e.g. literal int vs long mismatch), wrong number of arguments for overloads, ref/out parameters supplied incorrectly, member renamed in a library upgrade while the call still 'succeeds' at name level.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

        static void ThrowIfMethodMissing(string methodName, MethodInfo? method, object[] args)
#endif
        {
            if (method == null)
            {
                List<string> extractedTypeNames = new List<string>();
                foreach (object o in args)
                {
                    if (o is Expression expr)
                    {
                        extractedTypeNames.Add(expr.Type.GetFormattedName());
                    }
                    else
                    {
                        extractedTypeNames.Add(o.GetType().GetFormattedName());
                    }
                }

                throw new ArgumentException(string.Format(
                    CultureInfo.CurrentCulture,
                    Resources.MethodMissing,
                    typeof(T).Name,
                    methodName,
                    string.Join(
                        ", ",
                        extractedTypeNames.ToArray())));
            }
        }

        static void ThrowIfPublicMethod(MethodInfo method, string reflectedTypeName)
        {
            if (method.IsPublic)
            {
                throw new ArgumentException(string.Format(
                    CultureInfo.CurrentCulture,
                    Resources.MethodIsPublic,
                    reflectedTypeName,

View on GitHub (pinned to 89a5be629c)