devlooped/moq · error · MissingMethodException

"public bool ( ) in class .

Error message

"public {0}bool {1}({2}) in class {3}."

What it means

MatcherAttributeMatcher throws MissingMethodException when a [Matcher] attribute-marked method cannot be resolved: the validator method with the expected signature (public, matching parameter types, same return bool) does not exist on the declaring type. The error message spells out the exact required signature.

Solutions

  1. Make the validator method public, with signature `public bool MethodName(params...)` matching the expected parameter types shown in the message
  2. Match static-ness: add `static` if the message shows the call is static
  3. Ensure parameter types in the matcher method exactly match those of the mocked method call

Example fix

// before
private bool InRange(int value) => value >= 1 && value <= 10;
// after
public bool InRange(int value) => value >= 1 && value <= 10;
Defensive patterns

Strategy: validation

Validate before calling

var m = typeof(MyMatcher).GetMethod("InRange", new[] { typeof(int) });
if (m == null || !m.IsPublic || m.ReturnType != typeof(bool)) throw new InvalidOperationException("Matcher validator must be public bool with matching params");

Type guard

static bool IsValidMatcherMethod(MethodInfo? mi) => mi is { IsPublic: true } && mi.ReturnType == typeof(bool);

Try / catch

try { mock.Setup(m => m.Do(InRange(5))); } catch (MissingMethodException ex) when (ex.Message.Contains("bool")) { /* make validator public with exact signature */ }

Prevention

When it happens

Trigger: Using a custom [Matcher] class whose TryMatch/validate method is not public, is static without matching expectation, has wrong parameter types, or was renamed — typically surfaced when the matcher is used in a setup expression.

Common situations: Custom matcher classes copied from samples with private/protected validator methods; renamed methods after refactoring; parameter type lists out of sync with the matched method.

Related errors


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

Appendix: source

Thrown at src/Moq/Matchers/MatcherAttributeMatcher.cs:72

                method = call.Method.DeclaringType!.GetMethods(call.Method.Name)
                    .Where(m =>
                        m.IsGenericMethodDefinition &&
                        m.GetGenericArguments().Length ==
                            call.Method.GetGenericMethodDefinition().GetGenericArguments().Length &&
                        expectedParametersTypes.SequenceEqual(
                            m.MakeGenericMethod(genericArgs).GetParameters().Select(p => p.ParameterType)))
                    .Select(m => m.MakeGenericMethod(genericArgs))
                    .FirstOrDefault();
            }
            else
            {
                method = call.Method.DeclaringType!.GetMethod(call.Method.Name, expectedParametersTypes);
            }

            // throw if validatorMethod doesn't exists			
            if (method == null)
            {
                throw new MissingMethodException(string.Format(CultureInfo.CurrentCulture,
                    "public {0}bool {1}({2}) in class {3}.",
                    call.Method.IsStatic ? "static " : String.Empty,
                    call.Method.Name,
                    String.Join(", ", expectedParametersTypes.Select(x => x.Name).ToArray()),
                    call.Method.DeclaringType!.ToString()));
            }
            return method;
        }

        public bool Matches(object? argument, Type parameterType)
        {
            // use matcher Expression to get extra arguments
            var extraArgs = this.expression.Arguments.Select(ae => ((ConstantExpression)ae.PartialEval()).Value);
            var args = new[] { argument }.Concat(extraArgs).ToArray();
            // for static and non-static method
            var instance = this.expression.Object == null ? null : ((ConstantExpression)this.expression.Object.PartialEval()).Value;
            return (bool)validatorMethod.Invoke(instance, args)!;
        }

View on GitHub (pinned to 89a5be629c)