devlooped/moq · error · ArgumentException
Expression is not a setter
Error message
Expression is not a setter: {0} What it means
This guard validates that a lambda expression passed to a setup API is an assignment to a property or indexer (a setter), e.g. mock.SetupSet(x => x.Prop = value). If the expression body is not an assignment whose target is a property/indexer (or a Call that is a set accessor), Moq throws ArgumentException. It ensures SetupSet/SetupOnlySet receive valid setter expressions.
Solutions
- Use an assignment expression in SetupSet: mock.SetupSet(x => x.Prop = It.IsAny<string>()).
- Use mock.Setup(x => x.Prop) instead if you meant a getter setup.
- If assigning a field, convert the field to a property (or mock the interface) since fields cannot be mocked.
- Verify you are calling SetupSet/SetupOnlySet, not Setup.
Example fix
// before mock.SetupSet(x => x.Name); // getter, not a setter // after mock.SetupSet(x => x.Name = It.IsAny<string>());
Defensive patterns
Strategy: validation
Validate before calling
bool isSetterLambda(Expression<Func<T,object>> e) => e.Body is BinaryExpression b && b.NodeType == ExpressionType.Assign && (b.Left is MemberExpression || b.Left is IndexExpression);
Type guard
static bool IsSetterExpr<T>(Expression<Func<T, object>> e) => e.Body is BinaryExpression { NodeType: ExpressionType.Assign, Left: MemberExpression or IndexExpression }; Try / catch
try { mock.SetupSet(x => x.Name = It.IsAny<string>()); }
catch (ArgumentException ex) when (ex.Message.StartsWith("Expression is not a setter")) { /* use Setup for getters instead */ throw; } Prevention
- Use SetupSet only with assignment lambdas (x => x.Prop = value).
- Use Setup for getter/read setups.
- Convert public fields to properties before mocking.
- Do not wrap the lambda body in casts that hide the assignment.
When it happens
Trigger: Calling mock.SetupSet with a getter expression (x => x.Prop), a method call that is not a set accessor, a field assignment, or a compound/unsupported body.
Common situations: Confusing Setup with SetupSet (passing a getter where a setter is required); assigning to a public field instead of a property; setting up read-only or expression-bodied properties.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Unsupported expression
- Expression is not an event add
- Expression is not an event remove
- Property . does not have a setter.
- Resources.UnsupportedExpression (formatted with…
AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16).
Data as JSON: /api/errors/75eae045cd0284ec.
Report an issue: GitHub.
Appendix: source
Thrown at src/Moq/Guard.cs:76
public static void IsAssignmentToPropertyOrIndexer(LambdaExpression expression, string paramName)
{
Debug.Assert(expression != null);
switch (expression.Body.NodeType)
{
case ExpressionType.Assign:
var assignment = (BinaryExpression)expression.Body;
if (assignment.Left is MemberExpression || assignment.Left is IndexExpression) return;
break;
case ExpressionType.Call:
var call = (MethodCallExpression)expression.Body;
if (call.Method.IsSetAccessor()) return;
break;
}
throw new ArgumentException(
string.Format(
CultureInfo.CurrentCulture,
Resources.SetupNotSetter,
expression.ToStringFixed()),
paramName);
}
public static void IsOverridable(MethodInfo method, Expression expression)
{
if (method.IsStatic)
{
throw new NotSupportedException(
string.Format(
CultureInfo.CurrentCulture,
Resources.UnsupportedExpressionWithHint,
expression.ToStringFixed(),
string.Format(
CultureInfo.CurrentCulture,View on GitHub (pinned to 89a5be629c)