devlooped/moq · error · ArgumentException
Resources.UnsupportedExpression (formatted with expression)
Error message
Resources.UnsupportedExpression (formatted with expression)
What it means
Mock.Raise<T>(eventExpression, args) requires the lambda to be an event accessor expression (+= or -=). If the expression is anything else — a method call, property access, or plain member reference — Moq throws ArgumentException with Resources.UnsupportedExpression because it can only raise events through accessor syntax.
Solutions
- Use event accessor syntax: mock.Raise(x => x.MyEvent += null, EventArgs.Empty, ...)
- If you meant to configure a member, use mock.Setup(...) or mock.Verify(...) instead of Raise
- If you meant to invoke a method on the mock, call it on mock.Object or mock.Raise only for delegate/event members
- Check the lambda targets an event declared on an interface or non-sealed class
Example fix
// before mock.Raise(x => x.HandleOrder(order)); // method call, not an event accessor -> throws // after mock.Raise(x => x.OrderPlaced += null, new OrderEventArgs(order));
Defensive patterns
Strategy: validation
Validate before calling
static bool IsEventAccessorLambda<T>(System.Linq.Expressions.Expression<Action<T>> e) =>
e.Body is System.Linq.Expressions.Expression assign &&
(assign.NodeType == System.Linq.Expressions.ExpressionType.AddAssign ||
assign.NodeType == System.Linq.Expressions.ExpressionType.SubtractAssign);
// call before mock.Raise; if false, use Setup/Verify instead Type guard
static bool IsEvent(System.Linq.Expressions.Expression<Action<T>> e, out string? eventName)
{
eventName = null;
if (e.Body is System.Linq.Expressions.BinaryExpression b &&
(b.NodeType == System.Linq.Expressions.ExpressionType.AddAssign ||
b.NodeType == System.Linq.Expressions.ExpressionType.SubtractAssign) &&
b.Left is System.Linq.Expressions.MemberExpression me &&
me.Member is System.Reflection.EventInfo)
{
eventName = me.Member.Name;
return true;
}
return false;
} Try / catch
try
{
mock.Raise(x => x.MyEvent += null, EventArgs.Empty);
}
catch (ArgumentException ex) when (ex.Message.Contains("UnsupportedExpression"))
{
// correct the lambda to event accessor syntax or switch to Setup/Verify
} Prevention
- Remember mock.Raise only accepts event accessor lambdas (e => e.Evt += null or -= null)
- Use mock.Setup/mockedObject calls for method and property interactions
- Validate the expression shape in shared test helpers before delegating to Raise
When it happens
Trigger: Passing a non-accessor lambda to Raise, e.g. mock.Raise(x => x.MyMethod(), args) or mock.Raise(x => x.SomeProperty, value); any expression whose body is not an event add/remove assignment.
Common situations: Copy-paste between mock.Raise and mock.Verify/mocked member setups; misunderstanding that Raise targets events, not methods; typos where the += null part was omitted.
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
- Resources.SetupNotEventAdd (formatted with part.Expression)
- Resources.SetupNotEventRemove (formatted with…
- Unsupported expression
- Ref expression must evaluate to a constant value.
- Resources.UnsupportedExpression (formatted with…
AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16).
Data as JSON: /api/errors/e108d08615c2a99c.
Report an issue: GitHub.
Appendix: source
Thrown at src/Moq/Mock.cs:743
.SingleOrDefault(e => e.GetAddMethod(true) == implementingMethod)
?? throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.SetupNotEventAdd,
part.Expression));
}
else if (method.IsEventRemoveAccessor())
{
var implementingMethod = method.GetImplementingMethod(mock.Object.GetType());
@event = implementingMethod.DeclaringType!.GetEvents(bindingFlags)
.SingleOrDefault(e => e.GetRemoveMethod(true) == implementingMethod)
?? throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.SetupNotEventRemove,
part.Expression));
}
else
{
throw new ArgumentException(
string.Format(
CultureInfo.CurrentCulture,
Resources.UnsupportedExpression,
expression));
}
if (mock.EventHandlers.TryGet(@event, out var handlers))
{
var returnType = handlers.GetMethodInfo().ReturnType;
if (returnType == typeof(Task) || returnType.FullName == "System.Threading.Tasks.ValueTask")
{
var invocationList = handlers.GetInvocationList();
var tasks = new List<Task>(invocationList.Length);
foreach (var handler in invocationList)
{
var returnValue = handler.InvokePreserveStack(arguments);
if (returnValue is Task task)
{View on GitHub (pinned to 89a5be629c)