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
- Make the validator method public, with signature `public bool MethodName(params...)` matching the expected parameter types shown in the message
- Match static-ness: add `static` if the message shows the call is static
- 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
- Keep [Matcher] validator methods public and bool-returning
- Keep validator parameter types identical to the matched method's
- Write a reflection-based unit test for custom matcher classes
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
- A matching constructor for the given arguments was not…
- ex.Message (re-thrown ArgumentException with paramName…
- Type does not have matching protected member
- Member . does not exist.
- No protected method . found whose signature is compatible…
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)