devlooped/moq · error · NotSupportedException
Expression involves a field access, which is not supported…
Error message
Expression {0} involves a field access, which is not supported. Use properties instead. What it means
Moq throws this NotSupportedException when a LINQ expression used in a setup (e.g. mock.Setup(...)) contains a field access instead of a property access. Moq matches setups via member expressions and only supports properties, methods, and indexers; CLR fields cannot be intercepted by the generated proxy.
Solutions
- Replace the public field with a property on the mocked type (public int X => field; or an auto-property).
- If you cannot change the type, set the field directly on the mock's real backing object (use Mock.Of / manual instantiation) instead of Setup, or wrap it behind an interface with properties.
- Use SetupSet/VerifySet only on properties; for field state checks, assert on the field value after invoking the code under test rather than setting it up via Moq.
Example fix
// before
mock.Setup(m => m.Name).Returns("x"); // Name is a public FIELD
// after
mock.Setup(m => m.Name).Returns("x"); // after converting Name to a property
// or if the class cannot change:
var real = new Customer { Name = "x" }; // set field directly, don't Setup it Defensive patterns
Strategy: validation
Validate before calling
static bool IsFieldAccess(LambdaExpression expr)
{
var body = expr.Body as MemberExpression;
return body?.Member is System.Reflection.FieldInfo;
}
// before mock.Setup: if (IsFieldAccess(expr)) throw/fix
Type guard
static bool IsProperty(LambdaExpression expr) =>
(expr.Body as System.Linq.Expressions.MemberExpression)?.Member is System.Reflection.PropertyInfo;
Try / catch
try { mock.Setup(expr).Returns(value); }
catch (NotSupportedException ex) when (ex.Message.Contains("field access"))
{
// convert the member to a property or set the field directly
}
Prevention
- Prefer properties over public fields in types designed for mocking
- Use nameof()/expression-based navigation in IDEs that flag field vs property misuse
- Review DTOs for public fields before mocking them
- Wrap field-based third-party types behind property-based interfaces
When it happens
Trigger: Calling mock.Setup(m => m.someField) or mock.Verify(m => m.someField) where someField is a public (or accessible) field on the mocked class; also passing a lambda body like m => m.field + 1 that reads a field inside a setup expression.
Common situations: Mocking legacy or DTO classes that expose public fields instead of properties; refactoring a property to a field; third-party/interop types with public fields; copy-pasting member names and accidentally picking a field.
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 property access
- It is impossible to call the provided strongly-typed…
- Resources.CallBaseCannotBeUsedWithDelegateMocks
AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16).
Data as JSON: /api/errors/0f117bbf025f9ed7.
Report an issue: GitHub.
Appendix: source
Thrown at src/Moq/Guard.cs:202
/// <see cref="ArgumentException"/> in the latter.
/// </summary>
public static void NotNullOrEmpty(string value, string paramName)
{
if (value == null)
{
throw new ArgumentNullException(paramName);
}
if (value.Length == 0)
{
throw new ArgumentException(Resources.ArgumentCannotBeEmpty, paramName);
}
}
public static void NotField(MemberExpression memberAccess)
{
if (memberAccess.Member is FieldInfo)
throw new NotSupportedException(
string.Format(
Resources.FieldsNotSupported,
memberAccess.ToStringFixed()));
}
public static void IsMockable(Type type)
{
if (!type.IsMockable())
{
throw new NotSupportedException(
string.Format(
Resources.TypeNotMockable,
type.GetFormattedName()));
}
}
public static void Positive(TimeSpan delay)
{View on GitHub (pinned to 89a5be629c)