devlooped/moq · error · ArgumentException

Resources.SetupNotEventRemove (formatted with…

Error message

Resources.SetupNotEventRemove (formatted with part.Expression)

What it means

Symmetric to the add-accessor case: when Raise resolves an event remove accessor (e => e.MyEvent -= null) but no event on the mock's concrete type exposes that method as its remove method, Moq throws ArgumentException with Resources.SetupNotEventRemove, because it cannot map the accessor back to its EventInfo.

Solutions

  1. Use mock.As<IInterface>().Raise(e => e.Event -= null, args) targeting the declaring interface
  2. Declare events once on a mockable (non-sealed) base and avoid hiding with 'new'
  3. Check that the event's declaring type is accessible to Moq's reflection (public or internals visible to DynamicProxyGenAssembly2)
  4. Invoke the event through production code or an OnEvent helper rather than Raise for exotic event layouts

Example fix

// before
mock.Raise(x => x.HiddenEvent -= null, EventArgs.Empty); // accessor not resolvable -> throws
// after
mock.As<IEventSource>().Raise(e => e.SourceEvent -= null, EventArgs.Empty);
Defensive patterns

Strategy: try-catch

Validate before calling

var evt = mock.Object.GetType().GetEvents()
    .FirstOrDefault(e => e.GetRemoveMethod(true) != null && e.Name == nameof(IEventSource.SourceEvent));
// null means Raise(e => e.SourceEvent -= null, ...) will throw

Try / catch

try
{
    mock.Raise(x => x.SourceEvent -= null, EventArgs.Empty);
}
catch (ArgumentException ex) when (ex.Message.Contains("SetupNotEventRemove"))
{
    mock.As<IEventSource>().Raise(e => e.SourceEvent -= null, EventArgs.Empty);
}

Prevention

When it happens

Trigger: mock.Raise(x => x.SomeEvent -= null, ...) where the remove accessor comes from an explicitly implemented interface event, a hidden/new event, or a type whose events are not visible under the binding flags used, leaving GetEvents(...).SingleOrDefault(e => e.GetRemoveMethod(true) == implementingMethod) empty.

Common situations: Explicit interface event implementations on mocked classes; duplicated event declarations across inheritance hierarchies; reflection over mock.Object.GetType() returning a subclass that hides the event.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16). Data as JSON: /api/errors/a69b45e089567fbf. Report an issue: GitHub.

Appendix: source

Thrown at src/Moq/Mock.cs:736

            if (parts.Count == 0)
            {
                EventInfo @event;
                if (method.IsEventAddAccessor())
                {
                    var implementingMethod = method.GetImplementingMethod(mock.Object.GetType());
                    @event = implementingMethod.DeclaringType!.GetEvents(bindingFlags)
                                               .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")
                    {

View on GitHub (pinned to 89a5be629c)