devlooped/moq · error · NotSupportedException
Resources.UnsupportedExpression (formatted with…
Error message
Resources.UnsupportedExpression (formatted with originalExpression)
What it means
MatcherFactory throws this NotSupportedException when the argument expression in a setup cannot be reduced to a supported matcher form. Moq supports constant expressions, member access (property/field), matchers like It.*, quoted expression trees (ExpressionMatcher), and array initializers; anything else falls through to this error.
Solutions
- Pre-compute the value into a local variable and pass the constant
- Replace the expression with an argument matcher: It.Is<T>(x => ...) or It.IsAny<T>()
- For ref/expr arguments, pass a constant or quoted expression Moq can reduce
Example fix
// before mock.Setup(m => m.Calculate(x + y)); // after var sum = x + y; mock.Setup(m => m.Calculate(It.Is<int>(v => v == sum)));
Defensive patterns
Strategy: try-catch
Validate before calling
// before setup, ensure arguments are constants or It matchers
foreach (var arg in args) if (!(arg is ConstantExpression || arg?.NodeType == ExpressionType.MemberAccess)) throw new InvalidOperationException("Unsupported setup argument"); Type guard
static bool IsSupportedSetupArg(Expression e) => e is ConstantExpression || e.NodeType is ExpressionType.MemberAccess or ExpressionType.Quote or ExpressionType.NewArrayInit;
Try / catch
try { mock.Setup(m => m.Method(Compute())); } catch (NotSupportedException ex) when (ex.Message.Contains("Unsupported expression")) { /* hoist to local, use It.Is */ } Prevention
- Never call methods or do arithmetic inside setup expressions
- Pre-compute values into locals before Setup
- Use It.IsAny/It.Is for dynamic arguments
When it happens
Trigger: Using an unsupported expression as a setup argument, e.g. method calls, arithmetic, lambdas, or other reducible-but-unsupported node types: `mock.Setup(m => m.Method(ComputeValue()))` or `m.Method(a + b)`.
Common situations: Developers embedding computed values or helper-method calls directly in setup expressions instead of matchers or constants.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Unsupported expression
- Unsupported expression
- Expression is not a setter
- Expression is not an event add
- Expression is not an event remove
AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16).
Data as JSON: /api/errors/3b07d304d33705af.
Report an issue: GitHub.
Appendix: source
Thrown at src/Moq/MatcherFactory.cs:196
if (expression.IsMatch(out var match))
{
return new Pair<IMatcher, Expression>(match, expression);
}
}
// Try reducing locals to get a constant.
var reduced = originalExpression.PartialEval();
if (reduced.NodeType == ExpressionType.Constant)
{
return new Pair<IMatcher, Expression>(new ConstantMatcher(((ConstantExpression)reduced).Value), reduced);
}
if (reduced.NodeType == ExpressionType.Quote)
{
return new Pair<IMatcher, Expression>(new ExpressionMatcher(((UnaryExpression)expression).Operand), reduced);
}
throw new NotSupportedException(
string.Format(CultureInfo.CurrentCulture, Resources.UnsupportedExpression, originalExpression));
}
}
}
View on GitHub (pinned to 89a5be629c)