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

  1. Use event accessor syntax: mock.Raise(x => x.MyEvent += null, EventArgs.Empty, ...)
  2. If you meant to configure a member, use mock.Setup(...) or mock.Verify(...) instead of Raise
  3. If you meant to invoke a method on the mock, call it on mock.Object or mock.Raise only for delegate/event members
  4. 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

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


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)