devlooped/moq · error · ArgumentException
Resources.ArgumentMatcherWillNeverMatch (formatted with…
Error message
Resources.ArgumentMatcherWillNeverMatch (formatted with matcher expression, operand type, parameter type)
What it means
Moq throws this ArgumentException during matcher creation when the matcher's matched-value type cannot be assigned to the mocked method's parameter type — i.e. the argument matcher will never match. It compares the operand type of a Convert expression against the parameter's type using IsAssignableFrom.
Solutions
- Change the matcher's generic type so it matches the method parameter type exactly
- Verify the overload being mocked and its parameter types
- If a conversion is intended, explicitly convert the matched value (e.g. It.Is<int>(...) on an object parameter won't work — match the declared type)
Example fix
// before mock.Setup(m => m.Save(It.Is<int>(id => id > 0))); // Save takes string // after mock.Setup(m => m.Save(It.Is<string>(s => int.Parse(s) > 0)));
Defensive patterns
Strategy: validation
Validate before calling
var paramType = typeof(IFoo).GetMethod(nameof(IFoo.Save))!.GetParameters()[0].ParameterType;
if (!paramType.IsAssignableFrom(typeof(int))) throw new InvalidOperationException("Matcher type must be assignable to parameter type"); Type guard
static bool MatcherMatchesParam<TParam>(Expression<Func<TParam, bool>> _) => typeof(TParam) == typeof(TParam); // align T with the method's declared parameter type
Try / catch
try { mock.Setup(m => m.Save(It.Is<int>(x => x > 0))); } catch (ArgumentException ex) when (ex.Message.Contains("never match")) { /* fix matcher generic type */ } Prevention
- Match It.Is<T>'s T to the parameter's declared type
- Re-run tests after signature refactors
- Prefer typed setup helpers over raw It.Is expressions
When it happens
Trigger: Setting up a call with an argument matcher (It.Is<T>, It.IsAny<T>) whose T differs incompatibly from the parameter type, e.g. `mock.Setup(m => m.Method(It.Is<int>(x => x > 5)))` on a method taking a string, or a conversion the parameter type cannot accept.
Common situations: Type mismatches after method signature changes/refactoring; using the wrong generic type argument to It.Is; overload resolution picking a different parameter type than expected.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Unsupported expression
- Property . does not have a getter.
- Property . does not have a setter.
- It is impossible to call the provided strongly-typed…
- Resources.UnsupportedExpression (formatted with…
AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16).
Data as JSON: /api/errors/a50c927212093fab.
Report an issue: GitHub.
Appendix: source
Thrown at src/Moq/MatcherFactory.cs:115
{
if (convertExpression.Operand.IsMatch(out var match))
{
Type matchedValuesType;
if (match.GetType().IsGenericType)
{
// If match type is `Match<int>`, matchedValuesType set to `int`
// Fix for https://github.com/moq/moq4/issues/1199
matchedValuesType = match.GetType().GenericTypeArguments[0];
}
else
{
matchedValuesType = convertExpression.Operand.Type;
}
if (!matchedValuesType.IsAssignableFrom(parameter.ParameterType))
{
throw new ArgumentException(
string.Format(
Resources.ArgumentMatcherWillNeverMatch,
convertExpression.Operand.ToStringFixed(),
convertExpression.Operand.Type.GetFormattedName(),
parameter.ParameterType.GetFormattedName()));
}
}
}
}
return MatcherFactory.CreateMatcher(argument);
}
public static Pair<IMatcher, Expression> CreateMatcher(Expression expression)
{
// Type inference on the call might
// do automatic conversion to the desired
// method argument type, and a Convert expression type View on GitHub (pinned to 89a5be629c)